package com.tiancheng.trade.settlement.service.settlement.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.tiancheng.trade.settlement.enums.*;
import com.tiancheng.trade.settlement.exception.BusinessException;
import com.tiancheng.trade.settlement.feign.MerchantPaymentChannelService;
import com.tiancheng.trade.settlement.feign.OrderService;
import com.tiancheng.trade.settlement.mapper.settlement.*;
import com.tiancheng.trade.settlement.model.settlement.MerchantContract;
import com.tiancheng.trade.settlement.model.settlement.SettlementBillData;
import com.tiancheng.trade.settlement.model.settlement.SettlementRule;
import com.tiancheng.trade.settlement.model.settlement.StatementCost;
import com.tiancheng.trade.settlement.service.settlement.IMerchantContractService;
import com.tiancheng.trade.settlement.service.settlement.ISettlementRuleService;
import com.tiancheng.trade.settlement.service.settlement.IStatementCostService;
import com.tiancheng.trade.settlement.vo.settlement.admin.res.SettlementBankAmountResVO;
import com.tiancheng.trade.settlement.vo.settlement.admin.res.SubOrderResVO;
import com.tiancheng.trade.settlement.vo.settlement.api.FlowSubOrderVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class StatementCostService implements IStatementCostService {

    @Autowired
    private StatementCostMapper costMapper;

    @Autowired
    private SettlementBillDataMapper billDataMapper;

    @Autowired
    private SettlementBillResultMapper resultMapper;

    @Autowired
    private PaymentOrderFinishMapper finishMapper;

    @Autowired
    private FlowSubOrderMapper subOrderMapper;

    @Autowired
    private OrderService orderService;

    @Autowired
    private IMerchantContractService contractService;

    @Autowired
    private ISettlementRuleService ruleService;

    @Autowired
    private MerchantPaymentChannelService merchantService;

    /**
     * 报表类型 1成本 2成本差异 3无合同 4补签合同
     * 按时间查询收入成本报表
     *
     * @param date
     * @return
     * @throws BusinessException
     */
    @Override
    public List<StatementCost> getStatementCostList(String date, String costType) throws BusinessException {
        List<StatementCost> list = costMapper.getStatementCost(date, costType);
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(a -> {
                a.setProjectType(StatementProjectTypeEnum.getDesc(a.getProjectType()));
            });
        }
        return list;
    }

    //报表类型 1成本 2成本差异 3无合同 4补签合同
    private int addStatementCost(String date, String costType) throws BusinessException {
        List<StatementCost> list = new ArrayList<StatementCost>();
        if (StatementCostTypeEnum.COST.getCode().equals(costType)) {
            list = convertStatementCost(date, costType);
        }
        if (StatementCostTypeEnum.COST_DIFF.getCode().equals(costType)) {
            list = convertStatementCostDiff(date, costType);
        }
        if (StatementCostTypeEnum.NO_CONTRACT.getCode().equals(costType)) {
            list = convertStatementNoContract(date, costType);
        }
        if (StatementCostTypeEnum.REP_CONTRACT.getCode().equals(costType)) {
            list = convertStatementRepContract(date, costType);
        }
        if (CollectionUtils.isNotEmpty(list)) {
            return costMapper.addStatementCost(list);
        }
        return 0;
    }

    /**
     * 报表类型 1成本 2成本差异 3无合同 4补签合同
     * 按时间查询收入成本报表修改
     *
     * @param date
     * @return
     * @throws BusinessException
     */
    @Override
    public int updateStatementCost(String date, String costType) throws BusinessException {
        costMapper.deleteStatementCost(date, costType);
        return addStatementCost(date, costType);
    }

    //所有成本差异数据组装
    private List<StatementCost> convertStatementCostDiff(String date, String costType) {
        List<StatementCost> list = new ArrayList<StatementCost>();
        //第1项 应收金额数据
        log.info("成本差异报表应收金额数据.");
        StatementCost costSubOrder = getSubOrder(date);
        costSubOrder.setStatisticsDate(date);
        costSubOrder.setCostType(costType);
        costSubOrder.setProjectName(StatementProjectNameEnum.RECEIVABLE.getDesc());
        list.add(costSubOrder);
        //第2项 实收金额
        log.info("成本差异报表实收金额数据.");
        StatementCost receipt = getReceipt(date);
        receipt.setStatisticsDate(date);
        receipt.setCostType(costType);
        receipt.setProjectName(StatementProjectNameEnum.RECEIPTS.getDesc());
        list.add(receipt);

        //第3项 交易差异
        log.info("成本差异报表交易差异数据.");
        StatementCost diffCost = getDiffCost(costSubOrder, receipt);
        diffCost.setStatisticsDate(date);
        diffCost.setCostType(costType);
        diffCost.setProjectName(StatementProjectNameEnum.TRANSACTION.getDesc());
        list.add(diffCost);

        //第4项 流水差异数据信息
        log.info("成本差异报表流水差异数据.");
        List<FlowSubOrderVO> diffOrderDateList = subOrderMapper.getDiffAmount(date);
        if (CollectionUtils.isNotEmpty(diffOrderDateList)) {
            List<StatementCost> clearCostList = getOrderCostDiff(diffOrderDateList, date, costType);
            list.addAll(clearCostList);
        }

        //第5项 核销金额数据
        log.info("成本差异报表核销金额数据.");
        List<SettlementBillData> billDataList = billDataMapper.getVerifiedAmountCost(date);
        StatementCost verifiedOrder = getVerified(billDataList);
        verifiedOrder.setStatisticsDate(date);
        verifiedOrder.setCostType(costType);
        verifiedOrder.setProjectName(StatementProjectNameEnum.WRITE_OFF.getDesc());
        list.add(verifiedOrder);

        //第6项 平台服务费 合作模式是平台和清分，则该项=销售价-结算价，若合作模式为自营，则为0
        log.info("成本差异报表平台服务费.");
        StatementCost platService = getPlatService(costSubOrder, billDataList);
        platService.setStatisticsDate(date);
        platService.setCostType(costType);
        platService.setProjectName(StatementProjectNameEnum.PLATFORM.getDesc());
        list.add(platService);

        //第7项 银行资金数据
        log.info("成本差异报表银行资金数据.");
        List<SettlementBankAmountResVO> billResultList = resultMapper.getBankAmount(date);
        StatementCost bankAmount = getBankAmount(billResultList);
        bankAmount.setStatisticsDate(date);
        bankAmount.setCostType(costType);
        bankAmount.setProjectName(StatementProjectNameEnum.BANK_CAPITAL.getDesc());
        list.add(bankAmount);

        //第8项 获取资金差异
        log.info("成本差异报表获取资金差异数据.");
        StatementCost diffBankAmount = getDiffBankAmount(verifiedOrder, platService, bankAmount);
        diffBankAmount.setStatisticsDate(date);
        diffBankAmount.setCostType(costType);
        diffBankAmount.setProjectName(StatementProjectNameEnum.CAPITAL_DIFF.getDesc());
        list.add(diffBankAmount);

        //第9项 清分差异数据信息
        log.info("成本差异报表清分差异数据信息数据.");
        List<SettlementBankAmountResVO> diffDataList = resultMapper.getDiffAmount(date);
        if (CollectionUtils.isNotEmpty(diffDataList)) {
            List<StatementCost> clearCostList = getClearCostDiff(date, costType, diffDataList);
            list.addAll(clearCostList);
        }

        //第11项 无交易订单银行流水(￥),无交易订单清算资金(￥)
        log.info("成本差异报表无交易订单银行流水,无交易订单清算资金数据.");
        List<StatementCost> tranList = getNoTransaction(date, costType);
        list.addAll(tranList);

        return list;
    }

    //所有收入成本数据组装
    private List<StatementCost> convertStatementCost(String date, String costType) {
        List<StatementCost> list = new ArrayList<StatementCost>();
        //第1项 应收金额数据
        log.info("收入成本报表====应收金额数据.");
        StatementCost costSubOrder = getSubOrder(date);
        costSubOrder.setStatisticsDate(date);
        costSubOrder.setCostType(costType);
        costSubOrder.setProjectType(StatementProjectTypeEnum.RECEIPT.getCode());
        costSubOrder.setProjectName(StatementProjectNameEnum.RECEIVABLE.getDesc());
        list.add(costSubOrder);
        //第2项 核销金额数据
        log.info("收入成本报表====应收金额数据.");
        List<SettlementBillData> billDataList = billDataMapper.getVerifiedAmountCost(date);
        StatementCost verifiedOrder = getVerified(billDataList);
        verifiedOrder.setStatisticsDate(date);
        verifiedOrder.setCostType(costType);
        verifiedOrder.setProjectType(StatementProjectTypeEnum.RECEIPT.getCode());
        verifiedOrder.setProjectName(StatementProjectNameEnum.WRITE_OFF.getDesc());
        list.add(verifiedOrder);
        //第3项 实收金额
        log.info("收入成本报表====实收金额.");
        StatementCost receipt = getReceipt(date);
        receipt.setStatisticsDate(date);
        receipt.setCostType(costType);
        receipt.setProjectType(StatementProjectTypeEnum.RECEIPT.getCode());
        receipt.setProjectName(StatementProjectNameEnum.RECEIPTS.getDesc());
        list.add(receipt);

        //第4项 交易差异
        log.info("收入成本报表====交易差异.");
        StatementCost diffCost = getDiffCost(costSubOrder, receipt);
        diffCost.setStatisticsDate(date);
        diffCost.setCostType(costType);
        diffCost.setProjectType(StatementProjectTypeEnum.RECEIPT.getCode());
        diffCost.setProjectName(StatementProjectNameEnum.TRANSACTION.getDesc());
        list.add(diffCost);

        //第5项 平台服务费
        log.info("收入成本报表====平台服务费.");
        StatementCost platService = getPlatService(costSubOrder, billDataList);
        platService.setStatisticsDate(date);
        platService.setCostType(costType);
        platService.setProjectType(StatementProjectTypeEnum.RECEIPT.getCode());
        platService.setProjectName(StatementProjectNameEnum.PLATFORM.getDesc());
        list.add(platService);

        //第6项 结算价格 第7项 不含税成本 第8项 税额
        log.info("收入成本报表====结算价格 不含税成本 税额.");
        List<StatementCost> costList = getCostPriceList(billDataList, date, costType);
        list.addAll(costList);

        //第9项 银行资金数据
        log.info("收入成本报表====银行资金数据.");
        List<SettlementBankAmountResVO> billResultList = resultMapper.getBankAmount(date);
        StatementCost bankAmount = getBankAmount(billResultList);
        bankAmount.setStatisticsDate(date);
        bankAmount.setCostType(costType);
        bankAmount.setProjectName(StatementProjectNameEnum.BANK_CAPITAL.getDesc());
        list.add(bankAmount);

        //第10项 获取资金差异
        log.info("收入成本报表====获取资金差异.");
        StatementCost diffBankAmount = getDiffBankAmount(verifiedOrder, platService, bankAmount);
        diffBankAmount.setStatisticsDate(date);
        diffBankAmount.setCostType(costType);
        diffBankAmount.setProjectName(StatementProjectNameEnum.CAPITAL_DIFF.getDesc());
        list.add(diffBankAmount);

        //第11项 无交易订单银行流水(￥),无交易订单清算资金(￥)
        log.info("收入成本报表====无交易订单银行流水,无交易订单清算资金.");
        List<StatementCost> tranList = getNoTransaction(date, costType);
        list.addAll(tranList);
        return list;
    }

    //所有无合同数据组装
    private List<StatementCost> convertStatementNoContract(String date, String costType) {

        List<StatementCost> list = new ArrayList<StatementCost>();
        //第1项 应收金额数据
        log.info("收入无合同报表====应收金额数据.");
        StatementCost costSubOrder = getSubOrderNoContract(date);
        costSubOrder.setStatisticsDate(date);
        costSubOrder.setCostType(costType);
        costSubOrder.setProjectName(StatementProjectNameEnum.RECEIVABLE.getDesc());
        costSubOrder.setTicketClearing(costSubOrder.getTicketClearing());
        costSubOrder.setTicketSelf(costSubOrder.getTicketPlat().add(costSubOrder.getTicketSelf()));
        costSubOrder.setLineClearing(costSubOrder.getLineClearing());
        costSubOrder.setLineSelf(costSubOrder.getLinePlat().add(costSubOrder.getLineSelf()));
        costSubOrder.setFlightClearing(costSubOrder.getFlightClearing());
        costSubOrder.setFlightSelf(costSubOrder.getFlightPlat().add(costSubOrder.getFlightSelf()));
        costSubOrder.setHotelClearing(costSubOrder.getHotelClearing());
        costSubOrder.setHotelSelf(costSubOrder.getHotelSelf().add(costSubOrder.getHotelSelf()));
        costSubOrder.setChartererClearing(costSubOrder.getChartererClearing());
        costSubOrder.setChartererSelf(costSubOrder.getChartererSelf().add(costSubOrder.getChartererSelf()));
        list.add(costSubOrder);
        //第2项 实收金额
        log.info("收入无合同报表====实收金额数据.");
        StatementCost receipt = getNoContractReceipt(date);
        receipt.setStatisticsDate(date);
        receipt.setCostType(costType);
        receipt.setProjectName(StatementProjectNameEnum.RECEIPTS.getDesc());
        receipt.setTicketClearing(receipt.getTicketClearing());
        receipt.setTicketSelf(receipt.getTicketPlat().add(receipt.getTicketSelf()));
        receipt.setLineClearing(receipt.getLineClearing());
        receipt.setLineSelf(receipt.getLinePlat().add(receipt.getLineSelf()));
        receipt.setFlightClearing(receipt.getFlightClearing());
        receipt.setFlightSelf(receipt.getFlightPlat().add(receipt.getFlightSelf()));
        receipt.setHotelClearing(receipt.getHotelClearing());
        receipt.setHotelSelf(receipt.getHotelSelf().add(receipt.getHotelSelf()));
        receipt.setChartererClearing(receipt.getChartererClearing());
        receipt.setChartererSelf(receipt.getChartererSelf().add(receipt.getChartererSelf()));
        list.add(receipt);

        //第3项 交易差异
        log.info("收入无合同报表====交易差异数据.");
        StatementCost diffCost = new StatementCost();
        diffCost.setStatisticsDate(date);
        diffCost.setCostType(costType);
        diffCost.setProjectName(StatementProjectNameEnum.TRANSACTION.getDesc());
        diffCost.setTicketClearing(costSubOrder.getTicketClearing().subtract(receipt.getTicketClearing()));
        diffCost.setTicketSelf(costSubOrder.getTicketSelf().subtract(receipt.getTicketSelf()));
        diffCost.setLineClearing(costSubOrder.getLineClearing().subtract(receipt.getLineClearing()));
        diffCost.setLineSelf(costSubOrder.getLineSelf().subtract(receipt.getLineSelf()));
        diffCost.setFlightClearing(costSubOrder.getFlightClearing().subtract(receipt.getFlightClearing()));
        diffCost.setFlightSelf(costSubOrder.getFlightSelf().subtract(receipt.getFlightSelf()));
        diffCost.setHotelClearing(costSubOrder.getHotelClearing().subtract(receipt.getHotelClearing()));
        diffCost.setHotelSelf(costSubOrder.getHotelSelf().subtract(receipt.getHotelSelf()));
        diffCost.setChartererClearing(costSubOrder.getChartererClearing().subtract(receipt.getChartererClearing()));
        diffCost.setChartererSelf(costSubOrder.getChartererSelf().subtract(receipt.getChartererSelf()));
        list.add(diffCost);

        //第4项 流水差异数据信息

        log.info("收入无合同报表====流水差异数据信息.");
        List<FlowSubOrderVO> diffOrderDateList = subOrderMapper.getNoContractDiffAmount(date);
        if (CollectionUtils.isNotEmpty(diffOrderDateList)) {
            List<FlowSubOrderVO> newList = new ArrayList<FlowSubOrderVO>();
            List<String> listSt = diffOrderDateList.stream().map(FlowSubOrderVO::getMerchantCode).collect(Collectors.toList());
            List<String> merStr = listSt.stream().distinct().collect(Collectors.toList());
            //查询有合同数据,为过滤有合同数据准备
            List<MerchantContract> contractList = contractService.findContractByDate(merStr, date);
            //查询指定日期内签有合同,为过滤有合同数据准备
            List<MerchantContract> contractInList = contractService.findContractByInDate(merStr, date);
            if (CollectionUtils.isNotEmpty(contractInList)) {
                List<FlowSubOrderVO> subOrdeNotContList = new ArrayList<FlowSubOrderVO>();
                for (FlowSubOrderVO subOrderResVO : diffOrderDateList) {
                    boolean flag = true;
                    for (MerchantContract contract : contractInList) {
                        if (subOrderResVO.getMerchantCode().equals(contract.getMerchantCode())) {
                            flag = false;
                        }
                    }
                    if (flag) {
                        subOrdeNotContList.add(subOrderResVO);
                    }
                }
                diffOrderDateList = subOrdeNotContList;
            }
            if (CollectionUtils.isNotEmpty(contractList)) {
                for (FlowSubOrderVO subOrderResVO : diffOrderDateList) {
                    boolean flag = false;
                    for (MerchantContract contract : contractList) {
                        if (subOrderResVO.getId().equals(contract.getId().toString()) || "0".equals(subOrderResVO.getId())) {
                            flag = true;
                        }
                    }
                    if (flag) {
                        newList.add(subOrderResVO);
                    }
                }
                diffOrderDateList = newList;
            } else {
                diffOrderDateList = newList;
            }

            List<StatementCost> clearCostList = getOrderCostDiff(diffOrderDateList, date, costType);
            clearCostList.forEach(a -> {
                a.setTicketClearing(a.getTicketClearing());
                a.setTicketSelf(a.getTicketPlat().add(a.getTicketSelf()));
                a.setLineClearing(a.getLineClearing());
                a.setLineSelf(a.getLinePlat().add(a.getLineSelf()));
                a.setFlightClearing(a.getFlightClearing());
                a.setFlightSelf(a.getFlightPlat().add(a.getFlightSelf()));
                a.setHotelClearing(a.getHotelClearing());
                a.setHotelSelf(a.getHotelSelf().add(a.getHotelSelf()));
                a.setChartererClearing(a.getChartererClearing());
                a.setChartererSelf(a.getChartererSelf().add(a.getChartererSelf()));
            });
            list.addAll(clearCostList);
        }

        //第5项 核销金额数据
        log.info("收入无合同报表====核销金额数据信息.");
        List<SettlementBillData> billDataList = billDataMapper.getNoContractVerifiedAmount(date);
        //过滤有合同数据
        if (CollectionUtils.isNotEmpty(billDataList)) {
            List<SettlementBillData> newList = new ArrayList<SettlementBillData>();
            List<String> listSt = billDataList.stream().map(SettlementBillData::getMerchantCode).collect(Collectors.toList());
            List<String> merStr = listSt.stream().distinct().collect(Collectors.toList());
            //查询有合同数据,为过滤有合同数据准备
            List<MerchantContract> contractList = contractService.findContractByDate(merStr, date);
            //查询指定日期内签有合同,为过滤有合同数据准备
            List<MerchantContract> contractInList = contractService.findContractByInDate(merStr, date);
            if (CollectionUtils.isNotEmpty(contractInList)) {
                List<SettlementBillData> billNotContList = new ArrayList<SettlementBillData>();
                for (SettlementBillData subOrderResVO : billDataList) {
                    boolean flag = true;
                    for (MerchantContract contract : contractInList) {
                        if (subOrderResVO.getMerchantCode().equals(contract.getMerchantCode())) {
                            flag = false;
                        }
                    }
                    if (flag) {
                        billNotContList.add(subOrderResVO);
                    }
                }
                billDataList = billNotContList;
            }

            if (CollectionUtils.isNotEmpty(contractList)) {
                for (SettlementBillData subOrderResVO : billDataList) {
                    boolean flag = false;
                    for (MerchantContract contract : contractList) {
                        if (subOrderResVO.getId().toString().equals(contract.getId().toString()) || "0".equals(subOrderResVO.getId().toString())) {
                            flag = true;
                        }
                    }
                    if (flag) {
                        newList.add(subOrderResVO);
                    }
                }
                billDataList = newList;
            }
        }

        StatementCost verifiedOrder = getVerified(billDataList);
        verifiedOrder.setStatisticsDate(date);
        verifiedOrder.setCostType(costType);
        verifiedOrder.setProjectName(StatementProjectNameEnum.WRITE_OFF.getDesc());
        verifiedOrder.setTicketClearing(verifiedOrder.getTicketClearing());
        verifiedOrder.setTicketSelf(verifiedOrder.getTicketPlat().add(verifiedOrder.getTicketSelf()));
        verifiedOrder.setLineClearing(verifiedOrder.getLineClearing());
        verifiedOrder.setLineSelf(verifiedOrder.getLinePlat().add(verifiedOrder.getLineSelf()));
        verifiedOrder.setFlightClearing(verifiedOrder.getFlightClearing());
        verifiedOrder.setFlightSelf(verifiedOrder.getFlightPlat().add(verifiedOrder.getFlightSelf()));
        verifiedOrder.setHotelClearing(verifiedOrder.getHotelClearing());
        verifiedOrder.setHotelSelf(verifiedOrder.getHotelSelf().add(verifiedOrder.getHotelSelf()));
        verifiedOrder.setChartererClearing(verifiedOrder.getChartererClearing());
        verifiedOrder.setChartererSelf(verifiedOrder.getChartererSelf().add(verifiedOrder.getChartererSelf()));
        list.add(verifiedOrder);

        //第6项 平台服务费
        log.info("收入无合同报表====平台服务费信息.");
        StatementCost platService = getPlatService(costSubOrder, billDataList);
//        platService.setStatisticsDate(date);
//        platService.setCostType(costType);
//        platService.setProjectName(StatementProjectNameEnum.PLATFORM.getDesc());
//        platService.setTicketClearing(platService.getTicketClearing());
//        platService.setTicketSelf(platService.getTicketPlat().add(platService.getTicketSelf()));
//        platService.setLineClearing(platService.getLineClearing());
//        platService.setLineSelf(platService.getLinePlat().add(platService.getLineSelf()));
//        platService.setFlightClearing(platService.getFlightClearing());
//        platService.setFlightSelf(platService.getFlightPlat().add(platService.getFlightSelf()));
//        platService.setHotelClearing(platService.getHotelClearing());
//        platService.setHotelSelf(platService.getHotelSelf().add(platService.getHotelSelf()));
//        platService.setChartererClearing(platService.getChartererClearing());
//        platService.setChartererSelf(platService.getChartererSelf().add(platService.getChartererSelf()));
//        list.add(platService);

        //第7项 银行资金数据
        log.info("收入无合同报表====银行资金数据信息.");
        List<SettlementBankAmountResVO> billResultList = resultMapper.getNoContractBankAmount(date);

        List<SettlementBankAmountResVO> newBankAmountList = new ArrayList<SettlementBankAmountResVO>();
        //过滤有合同数据
        if (CollectionUtils.isNotEmpty(billResultList)) {
            List<String> listSt = billResultList.stream().map(SettlementBankAmountResVO::getMerchantCode).collect(Collectors.toList());
            List<String> merStr = listSt.stream().distinct().collect(Collectors.toList());
            //查询有合同数据,为过滤有合同数据准备
            List<MerchantContract> contractList = contractService.findContractByDate(merStr, date);
            //查询指定日期内签有合同,为过滤有合同数据准备
            List<MerchantContract> contractInList = contractService.findContractByInDate(merStr, date);
            if (CollectionUtils.isNotEmpty(contractInList)) {
                List<SettlementBankAmountResVO> bankNotContList = new ArrayList<SettlementBankAmountResVO>();
                for (SettlementBankAmountResVO subOrderResVO : billResultList) {
                    boolean flag = true;
                    for (MerchantContract contract : contractInList) {
                        if (subOrderResVO.getMerchantCode().equals(contract.getMerchantCode())) {
                            flag = false;
                        }
                    }
                    if (flag) {
                        bankNotContList.add(subOrderResVO);
                    }
                }
                billResultList = bankNotContList;
            }
            if (CollectionUtils.isNotEmpty(contractList)) {
                for (SettlementBankAmountResVO subOrderResVO : billResultList) {
                    boolean flag = false;
                    for (MerchantContract contract : contractList) {
                        if (subOrderResVO.getId().equals(contract.getId().toString()) || "0".equals(subOrderResVO.getId())) {
                            flag = true;
                        }
                    }
                    if (flag) {
                        newBankAmountList.add(subOrderResVO);
                    }
                }
                billResultList = newBankAmountList;
            }
        }

        StatementCost bankAmount = getBankAmount(billResultList);
        bankAmount.setStatisticsDate(date);
        bankAmount.setCostType(costType);
        bankAmount.setProjectName(StatementProjectNameEnum.BANK_CAPITAL.getDesc());
        bankAmount.setTicketClearing(bankAmount.getTicketClearing());
        bankAmount.setTicketSelf(bankAmount.getTicketPlat().add(bankAmount.getTicketSelf()));
        bankAmount.setLineClearing(bankAmount.getLineClearing());
        bankAmount.setLineSelf(bankAmount.getLinePlat().add(bankAmount.getLineSelf()));
        bankAmount.setFlightClearing(bankAmount.getFlightClearing());
        bankAmount.setFlightSelf(bankAmount.getFlightPlat().add(bankAmount.getFlightSelf()));
        bankAmount.setHotelClearing(bankAmount.getHotelClearing());
        bankAmount.setHotelSelf(bankAmount.getHotelSelf().add(bankAmount.getHotelSelf()));
        bankAmount.setChartererClearing(bankAmount.getChartererClearing());
        bankAmount.setChartererSelf(bankAmount.getChartererSelf().add(bankAmount.getChartererSelf()));
        list.add(bankAmount);

        //第8项 获取资金差异
        log.info("收入无合同报表====获取资金差异信息.");
        StatementCost diffBankAmount = getNoContractDiffBankAmount(verifiedOrder, platService, bankAmount);
        diffBankAmount.setStatisticsDate(date);
        diffBankAmount.setCostType(costType);
        diffBankAmount.setProjectName(StatementProjectNameEnum.CAPITAL_DIFF.getDesc());
        list.add(diffBankAmount);

        //第9项 清分差异数据信息
        log.info("收入无合同报表====清分差异数据信息.");
        List<SettlementBankAmountResVO> diffDataList = resultMapper.getNoContractDiffAmount(date);
        if (CollectionUtils.isNotEmpty(diffDataList)) {
            List<SettlementBankAmountResVO> clearAmountList = new ArrayList<SettlementBankAmountResVO>();
            //过滤有合同数据
            if (CollectionUtils.isNotEmpty(diffOrderDateList)) {
                List<String> listSt = diffOrderDateList.stream().map(FlowSubOrderVO::getMerchantCode).collect(Collectors.toList());
                List<String> merStr = listSt.stream().distinct().collect(Collectors.toList());
                //查询有合同数据,为过滤有合同数据准备
                List<MerchantContract> contractList = contractService.findContractByDate(merStr, date);
                //查询指定日期内签有合同,为过滤有合同数据准备
                List<MerchantContract> contractInList = contractService.findContractByInDate(merStr, date);
                if (CollectionUtils.isNotEmpty(contractInList)) {
                    List<SettlementBankAmountResVO> bankNotContList = new ArrayList<SettlementBankAmountResVO>();
                    for (SettlementBankAmountResVO subOrderResVO : diffDataList) {
                        boolean flag = true;
                        for (MerchantContract contract : contractInList) {
                            if (subOrderResVO.getMerchantCode().equals(contract.getMerchantCode())) {
                                flag = false;
                            }
                        }
                        if (flag) {
                            bankNotContList.add(subOrderResVO);
                        }
                    }
                    diffDataList = bankNotContList;
                }
                if (CollectionUtils.isNotEmpty(contractList)) {
                    for (SettlementBankAmountResVO subOrderResVO : diffDataList) {
                        boolean flag = false;
                        for (MerchantContract contract : contractList) {
                            if (subOrderResVO.getId().equals(contract.getId().toString()) || "0".equals(subOrderResVO.getId())) {
                                flag = true;
                            }
                        }
                        if (flag) {
                            clearAmountList.add(subOrderResVO);
                        }
                    }
                    diffDataList = clearAmountList;
                }
            }

            List<StatementCost> clearCostList = getClearCostDiff(date, costType, diffDataList);
            clearCostList.forEach(a -> {
                a.setTicketClearing(a.getTicketClearing());
                a.setTicketSelf(a.getTicketPlat().add(a.getTicketSelf()));
                a.setLineClearing(a.getLineClearing());
                a.setLineSelf(a.getLinePlat().add(a.getLineSelf()));
                a.setFlightClearing(a.getFlightClearing());
                a.setFlightSelf(a.getFlightPlat().add(a.getFlightSelf()));
                a.setHotelClearing(a.getHotelClearing());
                a.setHotelSelf(a.getHotelSelf().add(a.getHotelSelf()));
                a.setChartererClearing(a.getChartererClearing());
                a.setChartererSelf(a.getChartererSelf().add(a.getChartererSelf()));
            });
            list.addAll(clearCostList);
        }
        return list;

    }

    //所有补签合同数据组装
    private List<StatementCost> convertStatementRepContract(String date, String costType) {
        List<StatementCost> list = new ArrayList<StatementCost>();
        //应收金额数据
        log.info("补签合同报表====应收金额数据.");
        StatementCost costSubOrder = getSubOrderRepContract(date);
        //第1项 核销金额数据
        log.info("收入无合同报表====核销金额数据.");
        List<SettlementBillData> billDataList = billDataMapper.getRepContractVerifiedCost(date);
        StatementCost verifiedOrder = getVerified(billDataList);
        verifiedOrder.setStatisticsDate(date);
        verifiedOrder.setCostType(costType);
        verifiedOrder.setProjectName(StatementProjectNameEnum.WRITE_OFF.getDesc());
        list.add(verifiedOrder);

        //第2项 平台服务费
        log.info("收入无合同报表====平台服务费.");
        StatementCost platService = getPlatService(costSubOrder, billDataList);
        platService.setStatisticsDate(date);
        platService.setCostType(costType);
        platService.setProjectName(StatementProjectNameEnum.PLATFORM.getDesc());
        list.add(platService);

        //第3项 结算价格 第4项 不含税成本 第5项 税额
        log.info("收入无合同报表====结算价格,不含税成本,税额.");
        List<StatementCost> costList = getCostPriceList(billDataList, date, costType);
        list.addAll(costList);

        return list;
    }

    /**
     * 无合同报表
     * 第3项 实收金额
     * 实际支付金额
     *
     * @param date
     * @return
     */
    private StatementCost getNoContractReceipt(String date) {
        List<SubOrderResVO> subOrderList = finishMapper.getNoContractReceiptList(date);
        List<SubOrderResVO> newList = new ArrayList<SubOrderResVO>();
        //过滤有合同数据
        if (CollectionUtils.isNotEmpty(subOrderList)) {
            List<String> listSt = subOrderList.stream().map(SubOrderResVO::getMerchantCode).collect(Collectors.toList());
            List<String> merStr = listSt.stream().distinct().collect(Collectors.toList());
            //查询有合同数据,为过滤有合同数据准备
            List<MerchantContract> contractList = contractService.findContractByDate(merStr, date);
            //查询指定日期内签有合同,为过滤有合同数据准备
            List<MerchantContract> contractInList = contractService.findContractByInDate(merStr, date);
            if (CollectionUtils.isNotEmpty(contractInList)) {
                List<SubOrderResVO> subOrderNotContList = new ArrayList<SubOrderResVO>();
                for (SubOrderResVO subOrderResVO : subOrderList) {
                    boolean flag = true;
                    for (MerchantContract contract : contractInList) {
                        if (subOrderResVO.getMerchantCode().equals(contract.getMerchantCode())) {
                            flag = false;
                        }
                    }
                    if (flag) {
                        subOrderNotContList.add(subOrderResVO);
                    }
                }
                subOrderList = subOrderNotContList;
            }

            if (CollectionUtils.isNotEmpty(contractList)) {
                for (SubOrderResVO subOrderResVO : subOrderList) {
                    boolean flag = false;
                    for (MerchantContract contract : contractList) {
                        if (subOrderResVO.getId().equals(contract.getId().toString()) || "0".equals(subOrderResVO.getId())) {
                            flag = true;
                        }
                    }
                    if (flag) {
                        newList.add(subOrderResVO);
                    }
                }
            } else {
                newList = subOrderList;
            }
        }

        return getSubOrderCost(newList, date);
    }

    /**
     * 第3项 实收金额
     * 实际支付金额
     *
     * @param date
     * @return
     */
    private StatementCost getReceipt(String date) {
        StatementCost statementCost = new StatementCost();
        List<SubOrderResVO> subOrderList = finishMapper.getReceiptList(date);
        return getSubOrderCost(subOrderList, date);
    }

    /**
     * 第4项 交易差异
     * 交易差异=应收-实收
     *
     * @param costSubOrder
     * @param diffCost
     * @return
     */
    private StatementCost getDiffCost(StatementCost costSubOrder, StatementCost diffCost) {
        StatementCost statementCost = new StatementCost();
        statementCost.setHotelClearing(costSubOrder.getHotelClearing().subtract(diffCost.getHotelClearing()));
        statementCost.setHotelSelf(costSubOrder.getHotelSelf().subtract(diffCost.getHotelSelf()));
        statementCost.setHotelPlat(costSubOrder.getHotelPlat().subtract(diffCost.getHotelPlat()));

        statementCost.setFlightClearing(costSubOrder.getFlightClearing().subtract(diffCost.getFlightClearing()));
        statementCost.setFlightSelf(costSubOrder.getFlightSelf().subtract(diffCost.getFlightSelf()));
        statementCost.setFlightPlat(costSubOrder.getFlightPlat().subtract(diffCost.getFlightPlat()));

        statementCost.setTicketClearing(costSubOrder.getTicketClearing().subtract(diffCost.getTicketClearing()));
        statementCost.setTicketSelf(costSubOrder.getTicketSelf().subtract(diffCost.getTicketSelf()));
        statementCost.setTicketPlat(costSubOrder.getTicketPlat().subtract(diffCost.getTicketPlat()));

        statementCost.setLineClearing(costSubOrder.getLineClearing().subtract(diffCost.getLineClearing()));
        statementCost.setLineSelf(costSubOrder.getLineSelf().subtract(diffCost.getLineSelf()));
        statementCost.setLinePlat(costSubOrder.getLinePlat().subtract(diffCost.getLinePlat()));

        statementCost.setChartererClearing(costSubOrder.getChartererClearing().subtract(diffCost.getChartererClearing()));
        statementCost.setChartererSelf(costSubOrder.getChartererSelf().subtract(diffCost.getChartererSelf()));
        statementCost.setChartererPlat(costSubOrder.getChartererPlat().subtract(diffCost.getChartererPlat()));

        return statementCost;
    }


    /**
     * 第4项 无合同交易差异
     * 交易差异=应收-实收
     *
     * @param costSubOrder
     * @param diffCost
     * @return
     */
    private StatementCost getNoContractDiffCost(StatementCost costSubOrder, StatementCost diffCost) {
        StatementCost statementCost = new StatementCost();
        statementCost.setTicketClearing(costSubOrder.getTicketClearing().subtract(diffCost.getTicketClearing()));
        statementCost.setTicketSelf(costSubOrder.getTicketSelf().subtract(diffCost.getTicketSelf()));
        statementCost.setLineClearing(costSubOrder.getLineClearing().subtract(diffCost.getLineClearing()));
        statementCost.setLineSelf(costSubOrder.getLineSelf().subtract(diffCost.getLineSelf()));
        statementCost.setFlightClearing(costSubOrder.getFlightClearing().subtract(diffCost.getFlightClearing()));
        statementCost.setFlightSelf(costSubOrder.getFlightSelf().subtract(diffCost.getFlightSelf()));
        statementCost.setHotelClearing(costSubOrder.getHotelClearing().subtract(diffCost.getHotelClearing()));
        statementCost.setHotelSelf(costSubOrder.getHotelSelf().subtract(diffCost.getHotelSelf()));
        statementCost.setChartererClearing(costSubOrder.getChartererClearing().subtract(diffCost.getChartererClearing()));
        statementCost.setChartererSelf(costSubOrder.getChartererSelf().subtract(diffCost.getChartererSelf()));
        return statementCost;
    }


    /**
     * 第5项 获取平台服务费
     * 合作模式是平台和清分，则该项=销售价-结算价，若合作模式为自营，则为0
     *
     * @param costSubOrder
     * @param billDataList
     * @return
     */
    private StatementCost getPlatService(StatementCost costSubOrder, List<SettlementBillData> billDataList) {
        StatementCost statementCost = new StatementCost();
        BigDecimal bigNum1 = new BigDecimal(100);
        if (CollectionUtils.isNotEmpty(billDataList)) {

            List<SettlementBillData> hotelCleaList = billDataList.stream().filter(x -> SettlementTypeEnum.CLEARING.getCode().equals(x.getSettlementType()) && OrderSourceEnum.HOTEL.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            statementCost.setHotelClearing(costSubOrder.getHotelClearing());

            List<SettlementBillData> hotelPlatList = billDataList.stream().filter(x -> SettlementTypeEnum.PLAT.getCode().equals(x.getSettlementType()) && OrderSourceEnum.HOTEL.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            statementCost.setHotelPlat(costSubOrder.getHotelPlat());

            List<SettlementBillData> flightCleaList = billDataList.stream().filter(x -> SettlementTypeEnum.CLEARING.getCode().equals(x.getSettlementType()) && OrderSourceEnum.FLIGHT.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            statementCost.setFlightClearing(costSubOrder.getFlightClearing());

            List<SettlementBillData> flightPlatList = billDataList.stream().filter(x -> SettlementTypeEnum.PLAT.getCode().equals(x.getSettlementType()) && OrderSourceEnum.FLIGHT.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            statementCost.setFlightPlat(costSubOrder.getFlightPlat());

            List<SettlementBillData> ticketClearList = billDataList.stream().filter(x -> SettlementTypeEnum.CLEARING.getCode().equals(x.getSettlementType()) && OrderSourceEnum.TICKET.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            statementCost.setTicketClearing(costSubOrder.getTicketClearing());

            List<SettlementBillData> ticketPlatList = billDataList.stream().filter(x -> SettlementTypeEnum.PLAT.getCode().equals(x.getSettlementType()) && OrderSourceEnum.TICKET.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            statementCost.setTicketPlat(costSubOrder.getTicketPlat());

        }
        return statementCost;
    }

    /**
     * 第6，7，8项 获取结算价格,不含税成本,税额
     * 商品成本价格只有自营才有结算价，清分和平台为0
     *
     * @param billDataList
     * @return
     */
    private List<StatementCost> getCostPriceList(List<SettlementBillData> billDataList, String date, String costType) {
        List<StatementCost> list = new ArrayList<StatementCost>();
        StatementCost statementCost = new StatementCost();
        statementCost.setStatisticsDate(date);
        statementCost.setCostType(costType);
        statementCost.setProjectType(StatementProjectTypeEnum.COST.getCode());
        statementCost.setProjectName(StatementProjectNameEnum.SETTLEMENT.getDesc());
        StatementCost statementCost2 = new StatementCost();
        statementCost2.setStatisticsDate(date);
        statementCost2.setCostType(costType);
        statementCost2.setProjectType(StatementProjectTypeEnum.COST.getCode());
        statementCost2.setProjectName(StatementProjectNameEnum.COST.getDesc());
        StatementCost statementCost3 = new StatementCost();
        statementCost3.setStatisticsDate(date);
        statementCost3.setCostType(costType);
        statementCost3.setProjectType(StatementProjectTypeEnum.COST.getCode());
        statementCost3.setProjectName(StatementProjectNameEnum.TAX_AMOUNT.getDesc());
        BigDecimal bigNum1 = new BigDecimal(100);
        if (CollectionUtils.isNotEmpty(billDataList)) {
            List<SettlementBillData> hotelSelfList = billDataList.stream().filter(x -> SettlementTypeEnum.SELF.getCode().equals(x.getSettlementType()) && OrderSourceEnum.HOTEL.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            Integer hotelSelf = hotelSelfList.stream().collect(Collectors.summingInt(SettlementBillData::getCostPrice));
            if (hotelSelf != 0) {
                //结算价格
                statementCost.setHotelSelf(new BigDecimal(hotelSelf).divide(bigNum1));
                BigDecimal rate = hotelSelfList.get(0).getRate().add(bigNum1).divide(bigNum1);
                BigDecimal hotelRate = new BigDecimal(hotelSelf.toString());
                //不含税成本
                BigDecimal bignum3 = hotelRate.divide(rate, 2, BigDecimal.ROUND_HALF_UP).divide(bigNum1, 2, BigDecimal.ROUND_HALF_UP);
                statementCost2.setHotelSelf(bignum3);
                //税额
                BigDecimal bignum4 = bignum3.multiply(hotelSelfList.get(0).getRate()).divide(bigNum1);
                statementCost3.setHotelSelf(bignum4);
            }

            List<SettlementBillData> flightSelfList = billDataList.stream().filter(x -> SettlementTypeEnum.SELF.getCode().equals(x.getSettlementType()) && OrderSourceEnum.FLIGHT.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            Integer flightSelf = flightSelfList.stream().collect(Collectors.summingInt(SettlementBillData::getCostPrice));
            if (flightSelf != 0) {
                //结算价格
                statementCost.setFlightSelf(new BigDecimal(flightSelf).divide(bigNum1));
                BigDecimal rate = flightSelfList.get(0).getRate().add(bigNum1).divide(bigNum1);
                BigDecimal flightRate = new BigDecimal(flightSelf.toString());
                //不含税成本
                BigDecimal bignum3 = flightRate.divide(rate, 2, BigDecimal.ROUND_HALF_UP).divide(bigNum1, 2, BigDecimal.ROUND_HALF_UP);
                statementCost2.setFlightSelf(bignum3);
                //税额
                BigDecimal bignum4 = bignum3.multiply(flightSelfList.get(0).getRate()).divide(bigNum1);
                statementCost3.setFlightSelf(bignum4);
            }

            List<SettlementBillData> ticketSelfList = billDataList.stream().filter(x -> SettlementTypeEnum.SELF.getCode().equals(x.getSettlementType()) && OrderSourceEnum.TICKET.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            Integer ticketSelf = ticketSelfList.stream().collect(Collectors.summingInt(SettlementBillData::getCostPrice));
            if (ticketSelf != 0) {
                //结算价格
                statementCost.setTicketSelf(new BigDecimal(ticketSelf).divide(bigNum1));
                BigDecimal rate = ticketSelfList.get(0).getRate().add(bigNum1).divide(bigNum1);
                BigDecimal ticketRate = new BigDecimal(ticketSelf.toString());
                //不含税成本
                BigDecimal bignum3 = ticketRate.divide(rate, 2, BigDecimal.ROUND_HALF_UP).divide(bigNum1, 2, BigDecimal.ROUND_HALF_UP);
                statementCost2.setTicketSelf(bignum3);
                //税额
                BigDecimal bignum4 = bignum3.multiply(ticketSelfList.get(0).getRate()).divide(bigNum1);
                statementCost3.setTicketSelf(bignum4);
            }

        }
        list.add(statementCost);
        list.add(statementCost2);
        list.add(statementCost3);
        return list;
    }

    /**
     * 第10项 无合同获取资金差异
     * 自营：核销金额-银行资金
     * 清分：平台服务费-银行资金
     * 平台：核销金额-银行资金
     *
     * @param bankAmount
     * @return
     */
    private StatementCost getNoContractDiffBankAmount(StatementCost verified, StatementCost platService, StatementCost bankAmount) {
        StatementCost statementCost = new StatementCost();

        statementCost.setTicketClearing(platService.getTicketClearing().subtract(bankAmount.getTicketClearing()));
        statementCost.setTicketSelf(verified.getTicketSelf().subtract(bankAmount.getTicketSelf()));
        statementCost.setLineClearing(platService.getLineClearing().subtract(bankAmount.getLineClearing()));
        statementCost.setLineSelf(verified.getLineSelf().subtract(bankAmount.getLineSelf()));
        statementCost.setFlightClearing(platService.getFlightClearing().subtract(bankAmount.getFlightClearing()));
        statementCost.setFlightSelf(verified.getFlightSelf().subtract(bankAmount.getFlightSelf()));
        statementCost.setHotelClearing(platService.getHotelClearing().subtract(bankAmount.getHotelClearing()));
        statementCost.setHotelSelf(verified.getHotelSelf().subtract(bankAmount.getHotelSelf()));
        statementCost.setChartererClearing(platService.getChartererClearing().subtract(bankAmount.getChartererClearing()));
        statementCost.setChartererSelf(verified.getChartererSelf().subtract(bankAmount.getChartererSelf()));

        return statementCost;
    }

    /**
     * 第10项 获取资金差异
     * 自营：核销金额-银行资金
     * 清分：平台服务费-银行资金
     * 平台：核销金额-银行资金
     *
     * @param bankAmount
     * @return
     */
    private StatementCost getDiffBankAmount(StatementCost verified, StatementCost platService, StatementCost bankAmount) {
        StatementCost statementCost = new StatementCost();
        statementCost.setHotelClearing(platService.getHotelClearing().subtract(bankAmount.getHotelClearing()));
        statementCost.setHotelSelf(verified.getHotelSelf().subtract(bankAmount.getHotelSelf()));
        statementCost.setHotelPlat(verified.getHotelPlat().subtract(bankAmount.getHotelPlat()));

        statementCost.setFlightClearing(platService.getFlightClearing().subtract(bankAmount.getFlightClearing()));
        statementCost.setFlightSelf(verified.getFlightSelf().subtract(bankAmount.getFlightSelf()));
        statementCost.setFlightPlat(verified.getFlightPlat().subtract(bankAmount.getFlightPlat()));

        statementCost.setTicketClearing(platService.getTicketClearing().subtract(bankAmount.getTicketClearing()));
        statementCost.setTicketSelf(verified.getTicketSelf().subtract(bankAmount.getTicketSelf()));
        statementCost.setTicketPlat(verified.getTicketPlat().subtract(bankAmount.getTicketPlat()));

        statementCost.setLineClearing(platService.getLineClearing().subtract(bankAmount.getLineClearing()));
        statementCost.setLineSelf(verified.getLineSelf().subtract(bankAmount.getLineSelf()));
        statementCost.setLinePlat(verified.getLinePlat().subtract(bankAmount.getLinePlat()));

        statementCost.setChartererClearing(platService.getChartererClearing().subtract(bankAmount.getChartererClearing()));
        statementCost.setChartererSelf(verified.getChartererSelf().subtract(bankAmount.getChartererSelf()));
        statementCost.setChartererPlat(verified.getChartererPlat().subtract(bankAmount.getChartererPlat()));
        return statementCost;
    }

    /**
     * 第11项 无交易订单银行流水/无交易订单清算资金
     *
     * @param date
     * @return
     */
    private List<StatementCost> getNoTransaction(String date, String costType) {
        List<StatementCost> list = new ArrayList<StatementCost>();
        StatementCost statementCost = new StatementCost();
        statementCost.setStatisticsDate(date);
        statementCost.setCostType(costType);
        statementCost.setProjectName(StatementProjectNameEnum.BANK_STATEMENT.getDesc());
        BigDecimal bigNum1 = new BigDecimal("100");

        Integer payAmount = costMapper.getBankPayAmount(date);
        statementCost.setTicketSelf(new BigDecimal(payAmount).divide(bigNum1));
        list.add(statementCost);

        Integer clearAmount = costMapper.getBankClearAmount(date);
        StatementCost statementCost1 = new StatementCost();
        statementCost1.setStatisticsDate(date);
        statementCost1.setCostType(costType);
        statementCost1.setProjectName(StatementProjectNameEnum.BANK_STATEMENT.getDesc());
        statementCost1.setTicketSelf(new BigDecimal(clearAmount).divide(bigNum1));
        statementCost1.setProjectName(StatementProjectNameEnum.LIQUIDATION_FUNDS.getDesc());
        list.add(statementCost1);

        return list;
    }

    /**
     * 第9项 获取银行资金
     * 核销金额
     *
     * @param billDataList
     * @return
     */
    private StatementCost getBankAmount(List<SettlementBankAmountResVO> billDataList) {
        StatementCost statementCost = new StatementCost();
        BigDecimal num = new BigDecimal("100");
        if (CollectionUtils.isNotEmpty(billDataList)) {
            List<SettlementBankAmountResVO> hotelClearingList = billDataList.stream().filter(x -> SettlementTypeEnum.CLEARING.getCode().equals(x.getSettlementType()) && OrderSourceEnum.HOTEL.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(hotelClearingList)) {
                Integer hotelClearing = hotelClearingList.stream().collect(Collectors.summingInt(SettlementBankAmountResVO::getClearAmount));
                if (hotelClearing != 0) {
                    statementCost.setHotelClearing(new BigDecimal(hotelClearing).divide(num));
                }
            }
            List<SettlementBankAmountResVO> hotelSelfList = billDataList.stream().filter(x -> SettlementTypeEnum.SELF.getCode().equals(x.getSettlementType()) && OrderSourceEnum.HOTEL.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            Integer hotelSelf = hotelSelfList.stream().collect(Collectors.summingInt(SettlementBankAmountResVO::getClearAmount));
            if (hotelSelf != 0) {
                statementCost.setHotelSelf(new BigDecimal(hotelSelf).divide(num));
            }
            List<SettlementBankAmountResVO> hotelPlatList = billDataList.stream().filter(x -> SettlementTypeEnum.PLAT.getCode().equals(x.getSettlementType()) && OrderSourceEnum.HOTEL.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            Integer hotelPlat = hotelPlatList.stream().collect(Collectors.summingInt(SettlementBankAmountResVO::getClearAmount));
            if (hotelPlat != 0) {
                statementCost.setHotelPlat(new BigDecimal(hotelPlat).divide(num));
            }
            List<SettlementBankAmountResVO> flightClearingList = billDataList.stream().filter(x -> SettlementTypeEnum.CLEARING.getCode().equals(x.getSettlementType()) && OrderSourceEnum.FLIGHT.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            Integer flightClearing = flightClearingList.stream().collect(Collectors.summingInt(SettlementBankAmountResVO::getClearAmount));
            if (flightClearing != 0) {
                statementCost.setFlightClearing(new BigDecimal(flightClearing).divide(num));
            }
            List<SettlementBankAmountResVO> flightSelfList = billDataList.stream().filter(x -> SettlementTypeEnum.SELF.getCode().equals(x.getSettlementType()) && OrderSourceEnum.FLIGHT.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            Integer flightSelf = flightSelfList.stream().collect(Collectors.summingInt(SettlementBankAmountResVO::getClearAmount));
            if (flightSelf != 0) {
                statementCost.setFlightSelf(new BigDecimal(flightSelf).divide(num));
            }
            List<SettlementBankAmountResVO> flightPlatList = billDataList.stream().filter(x -> SettlementTypeEnum.PLAT.getCode().equals(x.getSettlementType()) && OrderSourceEnum.FLIGHT.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            Integer flightPlat = flightPlatList.stream().collect(Collectors.summingInt(SettlementBankAmountResVO::getClearAmount));
            if (flightPlat != 0) {
                statementCost.setFlightPlat(new BigDecimal(flightPlat).divide(num));
            }
            List<SettlementBankAmountResVO> ticketClearingList = billDataList.stream().filter(x -> SettlementTypeEnum.CLEARING.getCode().equals(x.getSettlementType()) && OrderSourceEnum.TICKET.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            Integer ticketClearing = ticketClearingList.stream().collect(Collectors.summingInt(SettlementBankAmountResVO::getClearAmount));
            if (ticketClearing != 0) {
                statementCost.setTicketClearing(new BigDecimal(ticketClearing).divide(num));
            }
            List<SettlementBankAmountResVO> ticketSelfList = billDataList.stream().filter(x -> SettlementTypeEnum.SELF.getCode().equals(x.getSettlementType()) && OrderSourceEnum.TICKET.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            Integer ticketSelf = ticketSelfList.stream().collect(Collectors.summingInt(SettlementBankAmountResVO::getClearAmount));
            if (ticketSelf != 0) {
                statementCost.setTicketSelf(new BigDecimal(ticketSelf).divide(num));
            }
            List<SettlementBankAmountResVO> ticketPlatList = billDataList.stream().filter(x -> SettlementTypeEnum.PLAT.getCode().equals(x.getSettlementType()) && OrderSourceEnum.TICKET.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            Integer ticketPlat = ticketPlatList.stream().collect(Collectors.summingInt(SettlementBankAmountResVO::getClearAmount));
            if (ticketPlat != 0) {
                statementCost.setTicketPlat(new BigDecimal(ticketPlat).divide(num));
            }
        }
        return statementCost;
    }

    /**
     * 第2项 获取核销金额
     * 核销金额
     *
     * @param billDataList
     * @return
     */
    private StatementCost getVerified(List<SettlementBillData> billDataList) {
        StatementCost statementCost = new StatementCost();
        BigDecimal num = new BigDecimal("100");
        if (CollectionUtils.isNotEmpty(billDataList)) {
            List<SettlementBillData> hotelClearingList = billDataList.stream().filter(x -> SettlementTypeEnum.CLEARING.getCode().equals(x.getSettlementType()) && OrderSourceEnum.HOTEL.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(hotelClearingList)) {
                Integer hotelClearing = hotelClearingList.stream().collect(Collectors.summingInt(SettlementBillData::getVerifiedAmount));
                statementCost.setHotelClearing(new BigDecimal(hotelClearing).divide(num));
            }
            List<SettlementBillData> hotelSelfList = billDataList.stream().filter(x -> SettlementTypeEnum.SELF.getCode().equals(x.getSettlementType()) && OrderSourceEnum.HOTEL.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(hotelSelfList)) {
                Integer hotelSelf = hotelSelfList.stream().collect(Collectors.summingInt(SettlementBillData::getVerifiedAmount));
                statementCost.setHotelSelf(new BigDecimal(hotelSelf).divide(num));
            }
            List<SettlementBillData> hotelPlatList = billDataList.stream().filter(x -> SettlementTypeEnum.PLAT.getCode().equals(x.getSettlementType()) && OrderSourceEnum.HOTEL.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(hotelPlatList)) {
                Integer hotelPlat = hotelPlatList.stream().collect(Collectors.summingInt(SettlementBillData::getVerifiedAmount));
                statementCost.setHotelPlat(new BigDecimal(hotelPlat).divide(num));
            }

            List<SettlementBillData> flightClearingList = billDataList.stream().filter(x -> SettlementTypeEnum.CLEARING.getCode().equals(x.getSettlementType()) && OrderSourceEnum.FLIGHT.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(flightClearingList)) {
                Integer flightClearing = flightClearingList.stream().collect(Collectors.summingInt(SettlementBillData::getVerifiedAmount));
                statementCost.setFlightClearing(new BigDecimal(flightClearing).divide(num));
            }
            List<SettlementBillData> flightSelfList = billDataList.stream().filter(x -> SettlementTypeEnum.SELF.getCode().equals(x.getSettlementType()) && OrderSourceEnum.FLIGHT.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(flightSelfList)) {
                Integer flightSelf = flightSelfList.stream().collect(Collectors.summingInt(SettlementBillData::getVerifiedAmount));
                statementCost.setFlightSelf(new BigDecimal(flightSelf).divide(num));
            }
            List<SettlementBillData> flightPlatList = billDataList.stream().filter(x -> SettlementTypeEnum.PLAT.getCode().equals(x.getSettlementType()) && OrderSourceEnum.FLIGHT.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(flightPlatList)) {
                Integer flightPlat = flightPlatList.stream().collect(Collectors.summingInt(SettlementBillData::getVerifiedAmount));
                statementCost.setFlightPlat(new BigDecimal(flightPlat).divide(num));
            }

            List<SettlementBillData> ticketClearingList = billDataList.stream().filter(x -> SettlementTypeEnum.CLEARING.getCode().equals(x.getSettlementType()) && OrderSourceEnum.TICKET.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(ticketClearingList)) {
                Integer ticketClearing = ticketClearingList.stream().collect(Collectors.summingInt(SettlementBillData::getVerifiedAmount));
                statementCost.setTicketClearing(new BigDecimal(ticketClearing).divide(num));
            }
            List<SettlementBillData> ticketSelfList = billDataList.stream().filter(x -> SettlementTypeEnum.SELF.getCode().equals(x.getSettlementType()) && OrderSourceEnum.TICKET.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(ticketSelfList)) {
                Integer ticketSelf = ticketSelfList.stream().collect(Collectors.summingInt(SettlementBillData::getVerifiedAmount));
                statementCost.setTicketSelf(new BigDecimal(ticketSelf).divide(num));
            }
            List<SettlementBillData> ticketPlatList = billDataList.stream().filter(x -> SettlementTypeEnum.PLAT.getCode().equals(x.getSettlementType()) && OrderSourceEnum.TICKET.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(ticketPlatList)) {
                Integer ticketPlat = ticketPlatList.stream().collect(Collectors.summingInt(SettlementBillData::getVerifiedAmount));
                statementCost.setTicketPlat(new BigDecimal(ticketPlat).divide(num));
            }

        }
        return statementCost;
    }

    /**
     * 第1项 获取应收金额
     * 订单总金额
     *
     * @param date
     * @return
     */
    private StatementCost getSubOrder(String date) {
        StatementCost statementCost = new StatementCost();
        List<SubOrderResVO> subOrderList = costMapper.getSubOrderList(date);
        return getSubOrderCost(subOrderList, date);
    }

    /**
     * 订单数据转换
     * 应收金额和实收金额(第1项和第3项数据统一转换)
     *
     * @param subOrderList
     * @return
     */
    private StatementCost setStatementCost(List<SubOrderResVO> subOrderList) {
        StatementCost statementCost = new StatementCost();
        BigDecimal num = new BigDecimal("100");
        List<SubOrderResVO> hotelClearingList = subOrderList.stream().filter(x -> SettlementTypeEnum.CLEARING.getCode().equals(x.getSettlementType()) && OrderSourceEnum.HOTEL.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(hotelClearingList)) {
            Integer hotelClearing = hotelClearingList.stream().collect(Collectors.summingInt(SubOrderResVO::getSubOrderAmount));
            statementCost.setHotelClearing(new BigDecimal(hotelClearing).divide(num));
        }
        List<SubOrderResVO> hotelSelfList = subOrderList.stream().filter(x -> SettlementTypeEnum.SELF.getCode().equals(x.getSettlementType()) && OrderSourceEnum.HOTEL.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(hotelSelfList)) {
            Integer hotelSelf = hotelSelfList.stream().collect(Collectors.summingInt(SubOrderResVO::getSubOrderAmount));
            statementCost.setHotelSelf(new BigDecimal(hotelSelf).divide(num));
        }
        List<SubOrderResVO> hotelPlatList = subOrderList.stream().filter(x -> SettlementTypeEnum.PLAT.getCode().equals(x.getSettlementType()) && OrderSourceEnum.HOTEL.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(hotelPlatList)) {
            Integer hotelPlat = hotelPlatList.stream().collect(Collectors.summingInt(SubOrderResVO::getSubOrderAmount));
            statementCost.setHotelPlat(new BigDecimal(hotelPlat).divide(num));
        }

        List<SubOrderResVO> flightClearingList = subOrderList.stream().filter(x -> SettlementTypeEnum.CLEARING.getCode().equals(x.getSettlementType()) && OrderSourceEnum.FLIGHT.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(flightClearingList)) {
            Integer flightClearing = flightClearingList.stream().collect(Collectors.summingInt(SubOrderResVO::getSubOrderAmount));
            statementCost.setFlightClearing(new BigDecimal(flightClearing).divide(num));
        }
        List<SubOrderResVO> flightSelfList = subOrderList.stream().filter(x -> SettlementTypeEnum.SELF.getCode().equals(x.getSettlementType()) && OrderSourceEnum.FLIGHT.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(flightSelfList)) {
            Integer flightSelf = flightSelfList.stream().collect(Collectors.summingInt(SubOrderResVO::getSubOrderAmount));
            statementCost.setFlightSelf(new BigDecimal(flightSelf).divide(num));
        }
        List<SubOrderResVO> flightPlatList = subOrderList.stream().filter(x -> SettlementTypeEnum.PLAT.getCode().equals(x.getSettlementType()) && OrderSourceEnum.FLIGHT.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(flightPlatList)) {
            Integer flightPlat = flightPlatList.stream().collect(Collectors.summingInt(SubOrderResVO::getSubOrderAmount));
            statementCost.setFlightPlat(new BigDecimal(flightPlat).divide(num));
        }

        List<SubOrderResVO> ticketClearingList = subOrderList.stream().filter(x -> SettlementTypeEnum.CLEARING.getCode().equals(x.getSettlementType()) && OrderSourceEnum.TICKET.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(ticketClearingList)) {
            Integer ticketClearing = ticketClearingList.stream().collect(Collectors.summingInt(SubOrderResVO::getSubOrderAmount));
            statementCost.setTicketClearing(new BigDecimal(ticketClearing).divide(num));
        }
        List<SubOrderResVO> ticketSelfList = subOrderList.stream().filter(x -> SettlementTypeEnum.SELF.getCode().equals(x.getSettlementType()) && OrderSourceEnum.TICKET.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(ticketSelfList)) {
            Integer ticketSelf = ticketSelfList.stream().collect(Collectors.summingInt(SubOrderResVO::getSubOrderAmount));
            statementCost.setTicketSelf(new BigDecimal(ticketSelf).divide(num));
        }
        List<SubOrderResVO> ticketPlatList = subOrderList.stream().filter(x -> SettlementTypeEnum.PLAT.getCode().equals(x.getSettlementType()) && OrderSourceEnum.TICKET.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(ticketPlatList)) {
            Integer ticketPlat = ticketPlatList.stream().collect(Collectors.summingInt(SubOrderResVO::getSubOrderAmount));
            statementCost.setTicketPlat(new BigDecimal(ticketPlat).divide(num));
        }

        return statementCost;
    }

    /**
     * 无合同报表
     * 第1项 获取应收金额
     * 订单总金额
     *
     * @param date
     * @return
     */
    private StatementCost getStatementNoContract(String date) {
        StatementCost statementCost = new StatementCost();
        List<SubOrderResVO> subOrderList = costMapper.getStatementNoContract(date);
        return getSubOrderCost(subOrderList, date);
    }


    /**
     * 无合同报表
     * 订单数据转换
     * 应收金额和实收金额(第1项和第3项数据统一转换)
     *
     * @param subOrderList
     * @return
     */
    private StatementCost setStatementNoContractCost(List<SubOrderResVO> subOrderList) {
        StatementCost statementCost = new StatementCost();
        BigDecimal num = new BigDecimal("100");
        List<SubOrderResVO> hotelClearingList = subOrderList.stream().filter(x -> SettlementTypeEnum.CLEARING.getCode().equals(x.getSettlementType()) && OrderSourceEnum.HOTEL.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(hotelClearingList)) {
            Integer hotelClearing = hotelClearingList.stream().collect(Collectors.summingInt(SubOrderResVO::getSubOrderAmount));
            statementCost.setHotelClearing(new BigDecimal(hotelClearing).divide(num));
        }
        List<SubOrderResVO> hotelSelfList = subOrderList.stream().filter(x -> SettlementTypeEnum.SELF.getCode().equals(x.getSettlementType()) && OrderSourceEnum.HOTEL.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(hotelSelfList)) {
            Integer hotelSelf = hotelSelfList.stream().collect(Collectors.summingInt(SubOrderResVO::getSubOrderAmount));
            statementCost.setHotelSelf(new BigDecimal(hotelSelf).divide(num));
        }
        List<SubOrderResVO> hotelPlatList = subOrderList.stream().filter(x -> SettlementTypeEnum.PLAT.getCode().equals(x.getSettlementType()) && OrderSourceEnum.HOTEL.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(hotelPlatList)) {
            Integer hotelPlat = hotelPlatList.stream().collect(Collectors.summingInt(SubOrderResVO::getSubOrderAmount));
            statementCost.setHotelPlat(new BigDecimal(hotelPlat).divide(num));
        }

        List<SubOrderResVO> flightClearingList = subOrderList.stream().filter(x -> SettlementTypeEnum.CLEARING.getCode().equals(x.getSettlementType()) && OrderSourceEnum.FLIGHT.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(flightClearingList)) {
            Integer flightClearing = flightClearingList.stream().collect(Collectors.summingInt(SubOrderResVO::getSubOrderAmount));
            statementCost.setFlightClearing(new BigDecimal(flightClearing).divide(num));
        }
        List<SubOrderResVO> flightSelfList = subOrderList.stream().filter(x -> SettlementTypeEnum.SELF.getCode().equals(x.getSettlementType()) && OrderSourceEnum.FLIGHT.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(flightSelfList)) {
            Integer flightSelf = flightSelfList.stream().collect(Collectors.summingInt(SubOrderResVO::getSubOrderAmount));
            statementCost.setFlightSelf(new BigDecimal(flightSelf).divide(num));
        }
        List<SubOrderResVO> flightPlatList = subOrderList.stream().filter(x -> SettlementTypeEnum.PLAT.getCode().equals(x.getSettlementType()) && OrderSourceEnum.FLIGHT.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(flightPlatList)) {
            Integer flightPlat = flightPlatList.stream().collect(Collectors.summingInt(SubOrderResVO::getSubOrderAmount));
            statementCost.setFlightPlat(new BigDecimal(flightPlat).divide(num));
        }

        List<SubOrderResVO> ticketClearingList = subOrderList.stream().filter(x -> SettlementTypeEnum.CLEARING.getCode().equals(x.getSettlementType()) && OrderSourceEnum.TICKET.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(ticketClearingList)) {
            Integer ticketClearing = ticketClearingList.stream().collect(Collectors.summingInt(SubOrderResVO::getSubOrderAmount));
            statementCost.setTicketClearing(new BigDecimal(ticketClearing).divide(num));
        }
        List<SubOrderResVO> ticketSelfList = subOrderList.stream().filter(x -> SettlementTypeEnum.SELF.getCode().equals(x.getSettlementType()) && OrderSourceEnum.TICKET.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(ticketSelfList)) {
            Integer ticketSelf = ticketSelfList.stream().collect(Collectors.summingInt(SubOrderResVO::getSubOrderAmount));
            statementCost.setTicketSelf(new BigDecimal(ticketSelf).divide(num));
        }
        List<SubOrderResVO> ticketPlatList = subOrderList.stream().filter(x -> SettlementTypeEnum.PLAT.getCode().equals(x.getSettlementType()) && OrderSourceEnum.TICKET.getCode().equals(x.getOrderSource())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(ticketPlatList)) {
            Integer ticketPlat = ticketPlatList.stream().collect(Collectors.summingInt(SubOrderResVO::getSubOrderAmount));
            statementCost.setTicketPlat(new BigDecimal(ticketPlat).divide(num));
        }

        return statementCost;
    }

    /**
     * 获取订单差异数据
     *
     * @param diffDataList
     * @return
     */
    private List<StatementCost> getOrderCostDiff(List<FlowSubOrderVO> diffDataList, String date, String costType) {
        BigDecimal num = new BigDecimal("100");
        List<StatementCost> list = new ArrayList<StatementCost>();
        if (CollectionUtils.isNotEmpty(diffDataList)) {
            //获取产品编号集合
            List<String> proStr = diffDataList.stream().map(FlowSubOrderVO::getProductCode).collect(Collectors.toList());
            List<String> proStr1 = proStr.stream().distinct().collect(Collectors.toList());
            //获取商户编号集合
            List<String> merStr = diffDataList.stream().map(FlowSubOrderVO::getMerchantCode).collect(Collectors.toList());
            List<String> merStr1 = merStr.stream().distinct().collect(Collectors.toList());
            //按商户编号和产品编号获取清分规则信息
            List<SettlementRule> ruleList = ruleService.getSettlementRuleByMerProCode(merStr1, proStr1, date);
            diffDataList.forEach(a -> {
                SettlementRule rule = ruleList.stream().filter(x -> x.getMerchantCode().equals(a.getMerchantCode()) && x.getProductCode().equals(a.getProductCode())).findAny().orElse(null);
                if (null != rule) {
                    a.setSettlementType(rule.getSettlementType());
                }
            });
            List<FlowSubOrderVO> newDdiffDataList = diffDataList.stream().filter(x -> StringUtils.isNotEmpty(x.getSettlementType())).collect(Collectors.toList());
            List<String> strList = newDdiffDataList.stream().filter(x -> StringUtils.isNotEmpty(x.getErrorReason())).map(FlowSubOrderVO::getErrorReason).collect(Collectors.toList());
            List<String> strList1 = strList.stream().distinct().collect(Collectors.toList());
            strList1.forEach(a -> {
                StatementCost statementCost = new StatementCost();
                statementCost.setStatisticsDate(date);
                statementCost.setProjectType(StatementProjectTypeEnum.ORDER_DIFF.getCode());
                statementCost.setCostType(costType);
                statementCost.setProjectName(a);
                if (StringUtils.isNotEmpty(ErrorReasonEnum.getDesc(a))) {
                    statementCost.setProjectName(ErrorReasonEnum.getDesc(a));
                }
                List<FlowSubOrderVO> hotelClearingList = newDdiffDataList.stream().filter(x -> SettlementTypeEnum.CLEARING.getCode().equals(x.getSettlementType()) && OrderSourceEnum.HOTEL.getCode().equals(x.getOrderSource()) && a.equals(x.getErrorReason())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(hotelClearingList)) {
                    Integer hotelClearing = hotelClearingList.stream().collect(Collectors.summingInt(FlowSubOrderVO::getErrorAmount));
                    statementCost.setHotelClearing(new BigDecimal(hotelClearing).divide(num));
                }
                List<FlowSubOrderVO> hotelSelfList = newDdiffDataList.stream().filter(x -> SettlementTypeEnum.SELF.getCode().equals(x.getSettlementType()) && OrderSourceEnum.HOTEL.getCode().equals(x.getOrderSource()) && a.equals(x.getErrorReason())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(hotelSelfList)) {
                    Integer hotelSelf = hotelSelfList.stream().collect(Collectors.summingInt(FlowSubOrderVO::getErrorAmount));
                    statementCost.setHotelSelf(new BigDecimal(hotelSelf).divide(num));
                }
                List<FlowSubOrderVO> hotelPlatList = newDdiffDataList.stream().filter(x -> SettlementTypeEnum.PLAT.getCode().equals(x.getSettlementType()) && OrderSourceEnum.HOTEL.getCode().equals(x.getOrderSource()) && a.equals(x.getErrorReason())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(hotelPlatList)) {
                    Integer hotelPlat = hotelPlatList.stream().collect(Collectors.summingInt(FlowSubOrderVO::getErrorAmount));
                    statementCost.setHotelPlat(new BigDecimal(hotelPlat).divide(num));
                }

                List<FlowSubOrderVO> flightClearingList = newDdiffDataList.stream().filter(x -> SettlementTypeEnum.CLEARING.getCode().equals(x.getSettlementType()) && OrderSourceEnum.FLIGHT.getCode().equals(x.getOrderSource()) && a.equals(x.getErrorReason())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(flightClearingList)) {
                    Integer flightClearing = flightClearingList.stream().collect(Collectors.summingInt(FlowSubOrderVO::getErrorAmount));
                    statementCost.setFlightClearing(new BigDecimal(flightClearing).divide(num));
                }
                List<FlowSubOrderVO> flightSelfList = newDdiffDataList.stream().filter(x -> SettlementTypeEnum.SELF.getCode().equals(x.getSettlementType()) && OrderSourceEnum.FLIGHT.getCode().equals(x.getOrderSource()) && a.equals(x.getErrorReason())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(flightSelfList)) {
                    Integer flightSelf = flightSelfList.stream().collect(Collectors.summingInt(FlowSubOrderVO::getErrorAmount));
                    statementCost.setFlightSelf(new BigDecimal(flightSelf).divide(num));
                }
                List<FlowSubOrderVO> flightPlatList = newDdiffDataList.stream().filter(x -> SettlementTypeEnum.PLAT.getCode().equals(x.getSettlementType()) && OrderSourceEnum.FLIGHT.getCode().equals(x.getOrderSource()) && a.equals(x.getErrorReason())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(flightPlatList)) {
                    Integer flightPlat = flightPlatList.stream().collect(Collectors.summingInt(FlowSubOrderVO::getErrorAmount));
                    statementCost.setFlightPlat(new BigDecimal(flightPlat).divide(num));
                }

                List<FlowSubOrderVO> ticketClearingList = newDdiffDataList.stream().filter(x -> SettlementTypeEnum.CLEARING.getCode().equals(x.getSettlementType()) && OrderSourceEnum.TICKET.getCode().equals(x.getOrderSource()) && a.equals(x.getErrorReason())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(ticketClearingList)) {
                    Integer ticketClearing = ticketClearingList.stream().collect(Collectors.summingInt(FlowSubOrderVO::getErrorAmount));
                    statementCost.setTicketClearing(new BigDecimal(ticketClearing).divide(num));
                }
                List<FlowSubOrderVO> ticketSelfList = newDdiffDataList.stream().filter(x -> SettlementTypeEnum.SELF.getCode().equals(x.getSettlementType()) && OrderSourceEnum.TICKET.getCode().equals(x.getOrderSource()) && a.equals(x.getErrorReason())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(ticketSelfList)) {
                    Integer ticketSelf = ticketSelfList.stream().collect(Collectors.summingInt(FlowSubOrderVO::getErrorAmount));
                    statementCost.setTicketSelf(new BigDecimal(ticketSelf).divide(num));
                }
                List<FlowSubOrderVO> ticketPlatList = newDdiffDataList.stream().filter(x -> SettlementTypeEnum.PLAT.getCode().equals(x.getSettlementType()) && OrderSourceEnum.TICKET.getCode().equals(x.getOrderSource()) && a.equals(x.getErrorReason())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(ticketPlatList)) {
                    Integer ticketPlat = ticketPlatList.stream().collect(Collectors.summingInt(FlowSubOrderVO::getErrorAmount));
                    statementCost.setTicketPlat(new BigDecimal(ticketPlat).divide(num));
                }


                if (costType.equals(StatementCostTypeEnum.NO_CONTRACT.getCode())) {
                    statementCost.setTicketSelf(statementCost.getTicketPlat().add(statementCost.getTicketSelf()));
                    statementCost.setLineSelf(statementCost.getLinePlat().add(statementCost.getLineSelf()));
                    statementCost.setFlightSelf(statementCost.getFlightPlat().add(statementCost.getFlightSelf()));
                    statementCost.setHotelSelf(statementCost.getHotelSelf().add(statementCost.getHotelSelf()));
                    statementCost.setChartererSelf(statementCost.getChartererSelf().add(statementCost.getChartererSelf()));
                }
                list.add(statementCost);
            });

        }
        return list;
    }

    /**
     * 获取清分差异数据
     *
     * @param diffDataList
     * @return
     */
    private List<StatementCost> getClearCostDiff(String date, String costType, List<SettlementBankAmountResVO> diffDataList) {
        List<StatementCost> list = new ArrayList<StatementCost>();
        BigDecimal num = new BigDecimal("100");
        if (CollectionUtils.isNotEmpty(diffDataList)) {
            List<String> strList = diffDataList.stream().filter(x -> StringUtils.isNotEmpty(x.getErrorRemark())).map(SettlementBankAmountResVO::getErrorRemark).collect(Collectors.toList());
            List<String> strList1 = strList.stream().distinct().collect(Collectors.toList());
            strList1.forEach(a -> {
                StatementCost statementCost = new StatementCost();
                statementCost.setStatisticsDate(date);
                statementCost.setProjectType(StatementProjectTypeEnum.CLEAR_DIFF.getCode());
                statementCost.setCostType(costType);
                statementCost.setProjectName(a);
                if (StringUtils.isNotEmpty(ErrorReasonEnum.getDesc(a))) {
                    statementCost.setProjectName(ErrorReasonEnum.getDesc(a));
                }
                List<SettlementBankAmountResVO> hotelClearingList = diffDataList.stream().filter(x -> SettlementTypeEnum.CLEARING.getCode().equals(x.getSettlementType()) && OrderSourceEnum.HOTEL.getCode().equals(x.getOrderSource()) && a.equals(x.getErrorRemark())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(hotelClearingList)) {
                    Integer hotelClearing = hotelClearingList.stream().collect(Collectors.summingInt(SettlementBankAmountResVO::getErrorAmount));
                    statementCost.setHotelClearing(new BigDecimal(hotelClearing).divide(num));
                }
                List<SettlementBankAmountResVO> hotelSelfList = diffDataList.stream().filter(x -> SettlementTypeEnum.SELF.getCode().equals(x.getSettlementType()) && OrderSourceEnum.HOTEL.getCode().equals(x.getOrderSource()) && a.equals(x.getErrorRemark())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(hotelSelfList)) {
                    Integer hotelSelf = hotelSelfList.stream().collect(Collectors.summingInt(SettlementBankAmountResVO::getErrorAmount));
                    statementCost.setHotelSelf(new BigDecimal(hotelSelf).divide(num));
                }
                List<SettlementBankAmountResVO> hotelPlatList = diffDataList.stream().filter(x -> SettlementTypeEnum.PLAT.getCode().equals(x.getSettlementType()) && OrderSourceEnum.HOTEL.getCode().equals(x.getOrderSource()) && a.equals(x.getErrorRemark())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(hotelPlatList)) {
                    Integer hotelPlat = hotelPlatList.stream().collect(Collectors.summingInt(SettlementBankAmountResVO::getErrorAmount));
                    statementCost.setHotelPlat(new BigDecimal(hotelPlat).divide(num));
                }

                List<SettlementBankAmountResVO> flightClearingList = diffDataList.stream().filter(x -> SettlementTypeEnum.CLEARING.getCode().equals(x.getSettlementType()) && OrderSourceEnum.FLIGHT.getCode().equals(x.getOrderSource()) && a.equals(x.getErrorRemark())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(flightClearingList)) {
                    Integer flightClearing = flightClearingList.stream().collect(Collectors.summingInt(SettlementBankAmountResVO::getErrorAmount));
                    statementCost.setFlightClearing(new BigDecimal(flightClearing).divide(num));
                }
                List<SettlementBankAmountResVO> flightSelfList = diffDataList.stream().filter(x -> SettlementTypeEnum.SELF.getCode().equals(x.getSettlementType()) && OrderSourceEnum.FLIGHT.getCode().equals(x.getOrderSource()) && a.equals(x.getErrorRemark())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(flightSelfList)) {
                    Integer flightSelf = flightSelfList.stream().collect(Collectors.summingInt(SettlementBankAmountResVO::getErrorAmount));
                    statementCost.setFlightSelf(new BigDecimal(flightSelf).divide(num));
                }
                List<SettlementBankAmountResVO> flightPlatList = diffDataList.stream().filter(x -> SettlementTypeEnum.PLAT.getCode().equals(x.getSettlementType()) && OrderSourceEnum.FLIGHT.getCode().equals(x.getOrderSource()) && a.equals(x.getErrorRemark())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(flightPlatList)) {
                    Integer flightPlat = flightPlatList.stream().collect(Collectors.summingInt(SettlementBankAmountResVO::getErrorAmount));
                    statementCost.setFlightPlat(new BigDecimal(flightPlat).divide(num));
                }

                List<SettlementBankAmountResVO> ticketClearingList = diffDataList.stream().filter(x -> SettlementTypeEnum.CLEARING.getCode().equals(x.getSettlementType()) && OrderSourceEnum.TICKET.getCode().equals(x.getOrderSource()) && a.equals(x.getErrorRemark())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(ticketClearingList)) {
                    Integer ticketClearing = ticketClearingList.stream().collect(Collectors.summingInt(SettlementBankAmountResVO::getErrorAmount));
                    statementCost.setTicketClearing(new BigDecimal(ticketClearing).divide(num));
                }
                List<SettlementBankAmountResVO> ticketSelfList = diffDataList.stream().filter(x -> SettlementTypeEnum.SELF.getCode().equals(x.getSettlementType()) && OrderSourceEnum.TICKET.getCode().equals(x.getOrderSource()) && a.equals(x.getErrorRemark())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(ticketSelfList)) {
                    Integer ticketSelf = ticketSelfList.stream().collect(Collectors.summingInt(SettlementBankAmountResVO::getErrorAmount));
                    statementCost.setTicketSelf(new BigDecimal(ticketSelf).divide(num));
                }
                List<SettlementBankAmountResVO> ticketPlatList = diffDataList.stream().filter(x -> SettlementTypeEnum.PLAT.getCode().equals(x.getSettlementType()) && OrderSourceEnum.TICKET.getCode().equals(x.getOrderSource()) && a.equals(x.getErrorRemark())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(ticketPlatList)) {
                    Integer ticketPlat = ticketPlatList.stream().collect(Collectors.summingInt(SettlementBankAmountResVO::getErrorAmount));
                    statementCost.setTicketPlat(new BigDecimal(ticketPlat).divide(num));
                }

                list.add(statementCost);
            });

        }
        return list;
    }


    /**
     * 补签合同数据
     * 第1项 获取补签合同应收金额
     * 订单总金额
     *
     * @param date
     * @return
     */
    private StatementCost getSubOrderRepContract(String date) {
        StatementCost statementCost = new StatementCost();
        List<SubOrderResVO> subOrderList = costMapper.getSubOrderRepContractList(date);
        return getSubOrderCost(subOrderList, date);
    }


    /**
     * 无合同数据
     * 第1项 获取无合同应收金额
     * 订单总金额
     *
     * @param date
     * @return
     */
    private StatementCost getSubOrderNoContract(String date) {
        List<SubOrderResVO> subOrderList = costMapper.getStatementNoContract(date);
        List<SubOrderResVO> newList = new ArrayList<SubOrderResVO>();
        //过滤有合同数据
        if (CollectionUtils.isNotEmpty(subOrderList)) {
            List<String> listSt = subOrderList.stream().map(SubOrderResVO::getMerchantCode).collect(Collectors.toList());
            List<String> merStr = listSt.stream().distinct().collect(Collectors.toList());
            //查询有合同数据,为过滤有合同数据准备
            List<MerchantContract> contractList = contractService.findContractByDate(merStr, date);
            //查询指定日期内签有合同,为过滤有合同数据准备
            List<MerchantContract> contractInList = contractService.findContractByInDate(merStr, date);
            if (CollectionUtils.isNotEmpty(contractInList)) {
                List<SubOrderResVO> subOrderNotContList = new ArrayList<SubOrderResVO>();
                for (SubOrderResVO subOrderResVO : subOrderList) {
                    boolean flag = true;
                    for (MerchantContract contract : contractInList) {
                        if (subOrderResVO.getMerchantCode().equals(contract.getMerchantCode())) {
                            flag = false;
                        }
                    }
                    if (flag) {
                        subOrderNotContList.add(subOrderResVO);
                    }
                }
                subOrderList = subOrderNotContList;
            }

            if (CollectionUtils.isNotEmpty(contractList)) {
                for (SubOrderResVO subOrderResVO : subOrderList) {
                    boolean flag = false;
                    for (MerchantContract contract : contractList) {
                        if (subOrderResVO.getId().equals(contract.getId().toString()) || "0".equals(subOrderResVO.getId())) {
                            flag = true;
                        }
                    }
                    if (flag) {
                        newList.add(subOrderResVO);
                    }
                }
            } else {
                newList = subOrderList;
            }
        }
        return getSubOrderCost(newList, date);
    }

    /**
     * 业务侧产品编号转换成平台产品编号
     * 订单数据转换结算类型公共类
     *
     * @param subOrderList
     * @return
     */
    private StatementCost getSubOrderCost(List<SubOrderResVO> subOrderList, String date) {
        StatementCost statementCost = new StatementCost();
        if (CollectionUtils.isNotEmpty(subOrderList)) {
            //获取产品编号集合
            List<String> proStr = subOrderList.stream().map(SubOrderResVO::getProductCode).collect(Collectors.toList());
            List<String> proStr1 = proStr.stream().distinct().collect(Collectors.toList());
            //获取商户编号集合
            List<String> merStr = subOrderList.stream().map(SubOrderResVO::getMerchantCode).collect(Collectors.toList());
            List<String> merStr1 = merStr.stream().distinct().collect(Collectors.toList());
            //按商户编号和产品编号获取清分规则信息
            List<SettlementRule> ruleList = ruleService.getSettlementRuleByMerProCode(merStr1, proStr1, date);
            subOrderList.forEach(a -> {
                SettlementRule rule = ruleList.stream().filter(x -> x.getMerchantCode().equals(a.getMerchantCode()) && x.getProductCode().equals(a.getProductCode())).findAny().orElse(null);
                if (null != rule) {
                    a.setSettlementType(rule.getSettlementType());
                }
            });
            List<SubOrderResVO> newSubOrderList = subOrderList.stream().filter(x -> StringUtils.isNotEmpty(x.getSettlementType())).collect(Collectors.toList());
            return setStatementCost(newSubOrderList);
        }
        return statementCost;
    }

    /**
     * 收入陈本报表PDF导出
     *
     * @param date
     * @param costType
     * @param response
     * @throws Exception
     */
    private void statementCostPdf(String date, String costType, HttpServletResponse response) throws Exception {
        // 第一步：实例化一个document对象
        Document document = new Document();

        // 第二步：设置要到出的路径
        // FileOutputStream out = new FileOutputStream(reportPath + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()).toString() + ".pdf");

        //如果是浏览器通过request请求需要在浏览器中输出则使用下面方式
        OutputStream out = response.getOutputStream();

        // 第三步：设置字符 jar包中的字体格式
        // BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);

        //前端无法使用jar包中字体格式，只能按字体文件来设置
        String path = "http://yyn-static-resources-1254950508.file.myqcloud.com/fonts/simsun.ttc";
        BaseFont bfChinese = BaseFont.createFont(path + ",0", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        // 第四步：标题字体样式
        Font fontZH1 = new Font(bfChinese, 12.0F, 1);       // 主标题
        Font fontZH2 = new Font(bfChinese, 8.0F, 1);       // 副标题
        Font fontZH3 = new Font(bfChinese, 8.0F, 1);       // 内容
        // 第五步，将pdf文件输出到磁盘
        PdfWriter writer = PdfWriter.getInstance(document, out);

        // 第六步，打开生成的pdf文件
        document.open();

        List<StatementCost> costList = costMapper.getStatementCost(date, costType);
        DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime createTime = LocalDateTime.now();
        if (CollectionUtils.isNotEmpty(costList)) {
            createTime = costList.get(0).getCreatedDt();
        }
        // 第七步,设置内容
        String title1 = "                      云南腾云信息产业有限公司收入成本报表";
        String title2 = "报表统计月份:" + date + "                                                                              报表生成日期:" + sdf.format(createTime);

        document.add(new Paragraph(new Chunk(title1, fontZH1).setLocalDestination(title1)));
        document.add(new Paragraph("\n"));
        document.add(new Paragraph(new Chunk(title2, fontZH2).setLocalDestination(title2)));
        document.add(new Paragraph("\n"));
        // 创建table,注意这里的16是两列的意思,下面通过table.addCell添加的时候必须添加整行内容的所有列
        PdfPTable table1 = new PdfPTable(17);

        table1.setWidthPercentage(100.0F);
        table1.getDefaultCell().setHorizontalAlignment(1);

        PdfPCell cell0 = new PdfPCell();
        cell0.setUseAscender(true);
        cell0.setUseDescender(true);
        cell0.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell0.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell0.setColspan(2);//合并单元格
        cell0.setRowspan(2);
        cell0.setPhrase(new Phrase("项目", fontZH2));

        PdfPCell cell1 = new PdfPCell();
        cell1.setUseAscender(true);
        cell1.setUseDescender(true);
        cell1.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell1.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell1.setColspan(3);//合并单元格
        cell1.setPhrase(new Phrase("门票", fontZH2));

        PdfPCell cell2 = new PdfPCell();
        cell2.setUseAscender(true);
        cell2.setUseDescender(true);
        cell2.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell2.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell2.setColspan(3);//合并单元格
        cell2.setPhrase(new Phrase("线路", fontZH2));
        PdfPCell cell3 = new PdfPCell();
        cell3.setUseAscender(true);
        cell3.setUseDescender(true);
        cell3.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell3.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell3.setColspan(3);//合并单元格
        cell3.setPhrase(new Phrase("机票", fontZH2));
        PdfPCell cell4 = new PdfPCell();
        cell4.setUseAscender(true);
        cell4.setUseDescender(true);
        cell4.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell4.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell4.setColspan(3);//合并单元格
        cell4.setPhrase(new Phrase("酒店", fontZH2));
        PdfPCell cell5 = new PdfPCell();
        cell5.setUseAscender(true);
        cell5.setUseDescender(true);
        cell5.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell5.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell5.setColspan(3);//合并单元格
        cell5.setPhrase(new Phrase("租车", fontZH2));

        table1.addCell(cell0);
        table1.addCell(cell1);
        table1.addCell(cell2);
        table1.addCell(cell3);
        table1.addCell(cell4);
        table1.addCell(cell5);

        table1.addCell(new Paragraph("自营", fontZH3));
        table1.addCell(new Paragraph("平台", fontZH3));
        table1.addCell(new Paragraph("清分", fontZH3));
        table1.addCell(new Paragraph("自营", fontZH3));
        table1.addCell(new Paragraph("平台", fontZH3));
        table1.addCell(new Paragraph("清分", fontZH3));
        table1.addCell(new Paragraph("自营", fontZH3));
        table1.addCell(new Paragraph("平台", fontZH3));
        table1.addCell(new Paragraph("清分", fontZH3));
        table1.addCell(new Paragraph("自营", fontZH3));
        table1.addCell(new Paragraph("平台", fontZH3));
        table1.addCell(new Paragraph("清分", fontZH3));
        table1.addCell(new Paragraph("自营", fontZH3));
        table1.addCell(new Paragraph("平台", fontZH3));
        table1.addCell(new Paragraph("清分", fontZH3));

        PdfPCell cell6 = new PdfPCell();
        cell6.setUseAscender(true);
        cell6.setUseDescender(true);
        cell6.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell6.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell6.setColspan(1);//合并单元格
        cell6.setRowspan(5);
        cell6.setPhrase(new Phrase("收入(￥)", fontZH3));
        table1.addCell(cell6);

        PdfPTable table2 = new PdfPTable(4);

        table2.setWidthPercentage(100.0F);
        table2.getDefaultCell().setHorizontalAlignment(1);

        //PDF生成时一行一行的写数据，遇到竖列合并代码，只能按数据循环到那一列后，开始合并
        if (CollectionUtils.isNotEmpty(costList)) {
            int i = 0;
            for (StatementCost a : costList) {
                i++;
                if (i == 6) {
                    PdfPCell cell7 = new PdfPCell();
                    cell7.setUseAscender(true);
                    cell7.setUseDescender(true);
                    cell7.setHorizontalAlignment(Element.ALIGN_CENTER);
                    cell7.setVerticalAlignment(Element.ALIGN_MIDDLE);
                    cell7.setColspan(1);//合并单元格
                    cell7.setRowspan(3);
                    cell7.setPhrase(new Phrase("成本(￥)", fontZH3));
                    table1.addCell(cell7);
                }
                if (i == 9 || i == 10) {
                    PdfPCell cell8 = new PdfPCell();
                    cell8.setUseAscender(true);
                    cell8.setUseDescender(true);
                    cell8.setHorizontalAlignment(Element.ALIGN_CENTER);
                    cell8.setVerticalAlignment(Element.ALIGN_MIDDLE);
                    cell8.setColspan(2);//合并单元格
                    cell8.setPhrase(new Phrase(a.getProjectName(), fontZH3));
                    table1.addCell(cell8);
                }
                if (i != 9 && i != 10 && i != 11 && i != 12) {
                    table1.addCell(new Paragraph(a.getProjectName(), fontZH3));
                }
                if (i != 11 && i != 12) {
                    table1.addCell(new Paragraph(a.getTicketSelf().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getTicketPlat().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getTicketClearing().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getLineSelf().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getLinePlat().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getLineClearing().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getFlightSelf().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getFlightPlat().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getFlightClearing().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getHotelSelf().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getHotelPlat().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getHotelClearing().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getChartererSelf().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getChartererPlat().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getChartererClearing().toString(), fontZH3));
                }
                if (i == 11 || i == 12) {

                    PdfPCell cell8 = new PdfPCell();
                    cell8.setUseAscender(true);
                    cell8.setUseDescender(true);
                    cell8.setHorizontalAlignment(Element.ALIGN_CENTER);
                    cell8.setVerticalAlignment(Element.ALIGN_MIDDLE);
                    cell8.setColspan(2);//合并单元格
                    cell8.setPhrase(new Phrase(a.getProjectName(), fontZH3));
                    table1.addCell(cell8);

                    PdfPCell cell9 = new PdfPCell();
                    cell9.setUseAscender(true);
                    cell9.setUseDescender(true);
                    cell9.setHorizontalAlignment(Element.ALIGN_LEFT);
                    cell9.setVerticalAlignment(Element.ALIGN_MIDDLE);
                    cell9.setColspan(15);//合并单元格
                    cell9.setPhrase(new Phrase(a.getTicketSelf().toString(), fontZH3));
                    table1.addCell(cell9);
                }
            }

        }
        document.add(table1);

        String title5 = "备注:应收金额=当月合同生效订单销售净额";
        String title6 = "     核销金额=当月合同生效核销订单金额";
        String title7 = "     实收金额=当月合同生效订单支付净额";
        String title8 = "     交易差异=应收金额-实收金额";
        String title9 = "     平台服务费=SUM(合同生效核销金额*佣金率)";
        String title10 = "     结算价格=SUM合同生效核销金额数据对应的结算价格";
        String title11 = "     不含税成本=SUM[合同有效结算价格/(订单所属税率+1)]";
        String title12 = "     税额=结算价格-不含税成本";
        String title13 = "     银行资金=核销金额数据对应的银行资金 （即608资金）";
        String title14 = "     资金差异=核销金额-银行资金";
        String title15 = "     无交易订单银行流水=无交易订单银行流水汇总";
        String title16 = "     无交易订单清算资金=无交易订单清分资金汇总";
        String title17 = "     酒店项目的合作模式中，平台是艺龙";

        document.add(new Paragraph(new Chunk(title5, fontZH2).setLocalDestination(title5)));
        document.add(new Paragraph(new Chunk(title6, fontZH2).setLocalDestination(title6)));
        document.add(new Paragraph(new Chunk(title7, fontZH2).setLocalDestination(title7)));
        document.add(new Paragraph(new Chunk(title8, fontZH2).setLocalDestination(title8)));
        document.add(new Paragraph(new Chunk(title9, fontZH2).setLocalDestination(title9)));
        document.add(new Paragraph(new Chunk(title10, fontZH2).setLocalDestination(title10)));
        document.add(new Paragraph(new Chunk(title11, fontZH2).setLocalDestination(title11)));
        document.add(new Paragraph(new Chunk(title12, fontZH2).setLocalDestination(title12)));
        document.add(new Paragraph(new Chunk(title13, fontZH2).setLocalDestination(title13)));
        document.add(new Paragraph(new Chunk(title14, fontZH2).setLocalDestination(title14)));
        document.add(new Paragraph(new Chunk(title15, fontZH2).setLocalDestination(title15)));
        document.add(new Paragraph(new Chunk(title16, fontZH2).setLocalDestination(title16)));
        document.add(new Paragraph(new Chunk(title17, fontZH2).setLocalDestination(title17)));
        // 第八步，关闭document
        document.close();
    }

    /**
     * 收入成本报表差异PDF导出
     *
     * @param date
     * @param costType
     * @param response
     * @throws Exception
     */
    private void statementCostDiffPdf(String date, String costType, HttpServletResponse response) throws Exception {
        // 第一步：实例化一个document对象
        Document document = new Document();

        // 第二步：设置要到出的路径
        // FileOutputStream out = new FileOutputStream(reportPath + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()).toString() + ".pdf");

        //如果是浏览器通过request请求需要在浏览器中输出则使用下面方式
        OutputStream out = response.getOutputStream();

        // 第三步：设置字符 jar包中的字体格式
        // BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);

        //前端无法使用jar包中字体格式，只能按字体文件来设置
        String path = "http://yyn-static-resources-1254950508.file.myqcloud.com/fonts/simsun.ttc";
        BaseFont bfChinese = BaseFont.createFont(path + ",0", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        // 第四步：标题字体样式
        Font fontZH1 = new Font(bfChinese, 12.0F, 1);       // 主标题
        Font fontZH2 = new Font(bfChinese, 8.0F, 1);       // 副标题
        Font fontZH3 = new Font(bfChinese, 8.0F, 1);       // 内容
        // 第五步，将pdf文件输出到磁盘
        PdfWriter writer = PdfWriter.getInstance(document, out);

        // 第六步，打开生成的pdf文件
        document.open();
        List<StatementCost> costList = costMapper.getStatementCost(date, costType);
        DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime createTime = LocalDateTime.now();
        if (CollectionUtils.isNotEmpty(costList)) {
            createTime = costList.get(0).getCreatedDt();
        }

        // 第七步,设置内容
        String title1 = "                      云南腾云信息产业有限公司收入成本差异报表";
        String title2 = "报表统计月份:" + date + "                                                                              报表生成日期:" + sdf.format(createTime);

        document.add(new Paragraph(new Chunk(title1, fontZH1).setLocalDestination(title1)));
        document.add(new Paragraph("\n"));
        document.add(new Paragraph(new Chunk(title2, fontZH2).setLocalDestination(title2)));
        document.add(new Paragraph("\n"));
        // 创建table,注意这里的17是两列的意思,下面通过table.addCell添加的时候必须添加整行内容的所有列
        PdfPTable table1 = new PdfPTable(17);

        table1.setWidthPercentage(100.0F);
        table1.getDefaultCell().setHorizontalAlignment(1);

        PdfPCell cell0 = new PdfPCell();
        cell0.setUseAscender(true);
        cell0.setUseDescender(true);
        cell0.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell0.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell0.setColspan(2);//合并单元格
        cell0.setRowspan(2);
        cell0.setPhrase(new Phrase("项目", fontZH2));

        PdfPCell cell1 = new PdfPCell();
        cell1.setUseAscender(true);
        cell1.setUseDescender(true);
        cell1.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell1.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell1.setColspan(3);//合并单元格
        cell1.setPhrase(new Phrase("门票", fontZH2));

        PdfPCell cell2 = new PdfPCell();
        cell2.setUseAscender(true);
        cell2.setUseDescender(true);
        cell2.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell2.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell2.setColspan(3);//合并单元格
        cell2.setPhrase(new Phrase("线路", fontZH2));
        PdfPCell cell3 = new PdfPCell();
        cell3.setUseAscender(true);
        cell3.setUseDescender(true);
        cell3.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell3.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell3.setColspan(3);//合并单元格
        cell3.setPhrase(new Phrase("机票", fontZH2));
        PdfPCell cell4 = new PdfPCell();
        cell4.setUseAscender(true);
        cell4.setUseDescender(true);
        cell4.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell4.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell4.setColspan(3);//合并单元格
        cell4.setPhrase(new Phrase("酒店", fontZH2));
        PdfPCell cell5 = new PdfPCell();
        cell5.setUseAscender(true);
        cell5.setUseDescender(true);
        cell5.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell5.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell5.setColspan(3);//合并单元格
        cell5.setPhrase(new Phrase("租车", fontZH2));

        table1.addCell(cell0);
        table1.addCell(cell1);
        table1.addCell(cell2);
        table1.addCell(cell3);
        table1.addCell(cell4);
        table1.addCell(cell5);

        table1.addCell(new Paragraph("自营", fontZH3));
        table1.addCell(new Paragraph("平台", fontZH3));
        table1.addCell(new Paragraph("清分", fontZH3));
        table1.addCell(new Paragraph("自营", fontZH3));
        table1.addCell(new Paragraph("平台", fontZH3));
        table1.addCell(new Paragraph("清分", fontZH3));
        table1.addCell(new Paragraph("自营", fontZH3));
        table1.addCell(new Paragraph("平台", fontZH3));
        table1.addCell(new Paragraph("清分", fontZH3));
        table1.addCell(new Paragraph("自营", fontZH3));
        table1.addCell(new Paragraph("平台", fontZH3));
        table1.addCell(new Paragraph("清分", fontZH3));
        table1.addCell(new Paragraph("自营", fontZH3));
        table1.addCell(new Paragraph("平台", fontZH3));
        table1.addCell(new Paragraph("清分", fontZH3));
        if (CollectionUtils.isNotEmpty(costList)) {
            List<StatementCost> orderList = costList.stream().filter(x -> StatementProjectTypeEnum.ORDER_DIFF.getCode().equals(x.getProjectType())).collect(Collectors.toList());
            List<StatementCost> clearList = costList.stream().filter(x -> StatementProjectTypeEnum.CLEAR_DIFF.getCode().equals(x.getProjectType())).collect(Collectors.toList());
            int orderSize = 0;
            if (CollectionUtils.isNotEmpty(orderList)) {
                orderSize = orderList.size();
            }
            int clearSize = 0;
            if (CollectionUtils.isNotEmpty(clearList)) {
                clearSize = clearList.size();
            }

            int i = 0;
            for (StatementCost a : costList) {
                i++;

                if (i <= 3 || (i > 3 + orderSize && i < 7 + orderSize + 1)) {
                    PdfPCell cell6 = new PdfPCell();
                    cell6.setUseAscender(true);
                    cell6.setUseDescender(true);
                    cell6.setHorizontalAlignment(Element.ALIGN_CENTER);
                    cell6.setVerticalAlignment(Element.ALIGN_MIDDLE);
                    cell6.setColspan(2);//合并单元格
                    cell6.setPhrase(new Phrase(a.getProjectName(), fontZH2));
                    table1.addCell(cell6);
                }

                if (i == 3 + 1 && CollectionUtils.isNotEmpty(orderList)) {
                    PdfPCell cell7 = new PdfPCell();
                    cell7.setUseAscender(true);
                    cell7.setUseDescender(true);
                    cell7.setHorizontalAlignment(Element.ALIGN_CENTER);
                    cell7.setVerticalAlignment(Element.ALIGN_MIDDLE);
                    cell7.setColspan(1);//合并单元格
                    cell7.setRowspan(orderSize);
                    cell7.setPhrase(new Phrase("流水差异类型(￥)", fontZH3));
                    table1.addCell(cell7);
//                    table1.addCell(new Paragraph(a.getProjectName(), fontZH3));
                }
                if (CollectionUtils.isNotEmpty(orderList) && 3 + 1 <= i && i < 3 + orderSize + 1) {
                    table1.addCell(new Paragraph(a.getProjectName(), fontZH3));
                }

                if (i == 7 + orderSize + 1 && CollectionUtils.isNotEmpty(clearList)) {
                    PdfPCell cell9 = new PdfPCell();
                    cell9.setUseAscender(true);
                    cell9.setUseDescender(true);
                    cell9.setHorizontalAlignment(Element.ALIGN_CENTER);
                    cell9.setVerticalAlignment(Element.ALIGN_MIDDLE);
                    cell9.setColspan(1);//合并单元格
                    cell9.setRowspan(clearSize);
                    cell9.setPhrase(new Phrase("清分差异类型(￥)", fontZH3));
                    table1.addCell(cell9);
//                    table1.addCell(new Paragraph(a.getProjectName(), fontZH3));
                }

                if (CollectionUtils.isNotEmpty(clearList) && 7 + orderSize + 1 <= i && i < 7 + clearSize + orderSize + 1) {
                    table1.addCell(new Paragraph(a.getProjectName(), fontZH3));
                }

                if (i != costList.size() - 1 && i != costList.size()) {
                    //table1.addCell(new Paragraph(a.getProjectName(), fontZH3));
                    table1.addCell(new Paragraph(a.getTicketSelf().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getTicketPlat().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getTicketClearing().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getLineSelf().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getLinePlat().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getLineClearing().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getFlightSelf().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getFlightPlat().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getFlightClearing().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getHotelSelf().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getHotelPlat().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getHotelClearing().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getChartererSelf().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getChartererPlat().toString(), fontZH3));
                    table1.addCell(new Paragraph(a.getChartererClearing().toString(), fontZH3));
                }
                if (i == costList.size() - 1 || i == costList.size()) {
                    PdfPCell cell8 = new PdfPCell();
                    cell8.setUseAscender(true);
                    cell8.setUseDescender(true);
                    cell8.setHorizontalAlignment(Element.ALIGN_CENTER);
                    cell8.setVerticalAlignment(Element.ALIGN_MIDDLE);
                    cell8.setColspan(2);//合并单元格
                    cell8.setPhrase(new Phrase(a.getProjectName(), fontZH3));
                    table1.addCell(cell8);

                    PdfPCell cell9 = new PdfPCell();
                    cell9.setUseAscender(true);
                    cell9.setUseDescender(true);
                    cell9.setHorizontalAlignment(Element.ALIGN_LEFT);
                    cell9.setVerticalAlignment(Element.ALIGN_MIDDLE);
                    cell9.setColspan(15);//合并单元格
                    cell9.setPhrase(new Phrase(a.getTicketSelf().toString(), fontZH3));
                    table1.addCell(cell9);
                }

            }
        }
        document.add(table1);
        String title5 = "备注:应收金额=当月合同生效订单交易净额";
        String title6 = "     实收金额=当月合同生效订单支付净额";
        String title7 = "     交易差异=应收金额-实收金额";
        String title8 = "     核销金额=当月合同生效核销订单金额";
        String title9 = "     平台服务费=SUM(合同生效核销金额*佣金率)";
        String title10 = "     银行资金=核销金额数据对应的银行资金";
        String title11 = "     资金差异=核销金额-银行资金";

        document.add(new Paragraph(new Chunk(title5, fontZH2).setLocalDestination(title5)));
        document.add(new Paragraph(new Chunk(title6, fontZH2).setLocalDestination(title6)));
        document.add(new Paragraph(new Chunk(title7, fontZH2).setLocalDestination(title7)));
        document.add(new Paragraph(new Chunk(title8, fontZH2).setLocalDestination(title8)));
        document.add(new Paragraph(new Chunk(title9, fontZH2).setLocalDestination(title9)));
        document.add(new Paragraph(new Chunk(title10, fontZH2).setLocalDestination(title10)));
        document.add(new Paragraph(new Chunk(title11, fontZH2).setLocalDestination(title11)));

        // 第八步，关闭document
        document.close();
    }

    /**
     * 收入成本报表补签合同PDF导出
     *
     * @param date
     * @param costType
     * @param response
     * @throws Exception
     */
    private void statementRepContractPdf(String date, String costType, HttpServletResponse response) throws Exception {
        // 第一步：实例化一个document对象
        Document document = new Document();

        // 第二步：设置要到出的路径
        // FileOutputStream out = new FileOutputStream(reportPath + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()).toString() + ".pdf");

        //如果是浏览器通过request请求需要在浏览器中输出则使用下面方式
        OutputStream out = response.getOutputStream();

        // 第三步：设置字符 jar包中的字体格式
        // BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);

        //前端无法使用jar包中字体格式，只能按字体文件来设置
        String path = "http://yyn-static-resources-1254950508.file.myqcloud.com/fonts/simsun.ttc";
        BaseFont bfChinese = BaseFont.createFont(path + ",0", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        // 第四步：标题字体样式
        Font fontZH1 = new Font(bfChinese, 12.0F, 1);       // 主标题
        Font fontZH2 = new Font(bfChinese, 8.0F, 1);       // 副标题
        Font fontZH3 = new Font(bfChinese, 8.0F, 1);       // 内容
        // 第五步，将pdf文件输出到磁盘
        PdfWriter writer = PdfWriter.getInstance(document, out);

        // 第六步，打开生成的pdf文件
        document.open();
        List<StatementCost> costList = costMapper.getStatementCost(date, costType);
        DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime createTime = LocalDateTime.now();
        if (CollectionUtils.isNotEmpty(costList)) {
            createTime = costList.get(0).getCreatedDt();
        }

        // 第七步,设置内容
        String title1 = "                      云南腾云信息产业有限公司补签合同报表";
        String title2 = "报表统计月份:" + date + "                                                                              报表生成日期:" + sdf.format(createTime);

        document.add(new Paragraph(new Chunk(title1, fontZH1).setLocalDestination(title1)));
        document.add(new Paragraph("\n"));
        document.add(new Paragraph(new Chunk(title2, fontZH2).setLocalDestination(title2)));
        document.add(new Paragraph("\n"));
        // 创建table,注意这里的16是两列的意思,下面通过table.addCell添加的时候必须添加整行内容的所有列
        PdfPTable table1 = new PdfPTable(16);
        table1.setWidthPercentage(100.0F);
        table1.getDefaultCell().setHorizontalAlignment(1);

        PdfPCell cell0 = new PdfPCell();
        cell0.setUseAscender(true);
        cell0.setUseDescender(true);
        cell0.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell0.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell0.setColspan(1);//合并单元格
        cell0.setRowspan(2);
        cell0.setPhrase(new Phrase("项目", fontZH2));

        PdfPCell cell1 = new PdfPCell();
        cell1.setUseAscender(true);
        cell1.setUseDescender(true);
        cell1.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell1.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell1.setColspan(3);//合并单元格
        cell1.setPhrase(new Phrase("门票", fontZH2));

        PdfPCell cell2 = new PdfPCell();
        cell2.setUseAscender(true);
        cell2.setUseDescender(true);
        cell2.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell2.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell2.setColspan(3);//合并单元格
        cell2.setPhrase(new Phrase("线路", fontZH2));
        PdfPCell cell3 = new PdfPCell();
        cell3.setUseAscender(true);
        cell3.setUseDescender(true);
        cell3.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell3.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell3.setColspan(3);//合并单元格
        cell3.setPhrase(new Phrase("机票", fontZH2));
        PdfPCell cell4 = new PdfPCell();
        cell4.setUseAscender(true);
        cell4.setUseDescender(true);
        cell4.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell4.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell4.setColspan(3);//合并单元格
        cell4.setPhrase(new Phrase("酒店", fontZH2));
        PdfPCell cell5 = new PdfPCell();
        cell5.setUseAscender(true);
        cell5.setUseDescender(true);
        cell5.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell5.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell5.setColspan(3);//合并单元格
        cell5.setPhrase(new Phrase("租车", fontZH2));

        table1.addCell(cell0);
        table1.addCell(cell1);
        table1.addCell(cell2);
        table1.addCell(cell3);
        table1.addCell(cell4);
        table1.addCell(cell5);

        table1.addCell(new Paragraph("自营", fontZH3));
        table1.addCell(new Paragraph("平台", fontZH3));
        table1.addCell(new Paragraph("清分", fontZH3));
        table1.addCell(new Paragraph("自营", fontZH3));
        table1.addCell(new Paragraph("平台", fontZH3));
        table1.addCell(new Paragraph("清分", fontZH3));
        table1.addCell(new Paragraph("自营", fontZH3));
        table1.addCell(new Paragraph("平台", fontZH3));
        table1.addCell(new Paragraph("清分", fontZH3));
        table1.addCell(new Paragraph("自营", fontZH3));
        table1.addCell(new Paragraph("平台", fontZH3));
        table1.addCell(new Paragraph("清分", fontZH3));
        table1.addCell(new Paragraph("自营", fontZH3));
        table1.addCell(new Paragraph("平台", fontZH3));
        table1.addCell(new Paragraph("清分", fontZH3));

        if (CollectionUtils.isNotEmpty(costList)) {
            costList.forEach(a -> {
                table1.addCell(new Paragraph(a.getProjectName(), fontZH3));
                table1.addCell(new Paragraph(a.getTicketSelf().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getTicketPlat().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getTicketClearing().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getLineSelf().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getLinePlat().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getLineClearing().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getFlightSelf().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getFlightPlat().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getFlightClearing().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getHotelSelf().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getHotelPlat().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getHotelClearing().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getChartererSelf().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getChartererPlat().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getChartererClearing().toString(), fontZH3));
            });
        }
        document.add(table1);

        String title8 = "备注:核销金额=当月补签合同核销订单金额";
        String title9 = "     平台服务费=SUM(当月补签合同核销订单金额*佣金率)";
        String title10 = "     结算价格=SUM当月补签合同核销金额数据对应的结算价格";
        String title11 = "     不含税成本=SUM[补签合同结算价格/（订单所属税率+1）]";
        String title12 = "     税额=结算价格-不含税成本";

        document.add(new Paragraph(new Chunk(title8, fontZH2).setLocalDestination(title8)));
        document.add(new Paragraph(new Chunk(title9, fontZH2).setLocalDestination(title9)));
        document.add(new Paragraph(new Chunk(title10, fontZH2).setLocalDestination(title10)));
        document.add(new Paragraph(new Chunk(title11, fontZH2).setLocalDestination(title11)));
        document.add(new Paragraph(new Chunk(title12, fontZH2).setLocalDestination(title12)));
        // 第八步，关闭document
        document.close();
    }

    /**
     * 收入成本无合同报表PDF导出
     *
     * @param date
     * @param costType
     * @param response
     * @throws Exception
     */
    private void statementNoContractPdf(String date, String costType, HttpServletResponse response) throws Exception {
        // 第一步：实例化一个document对象
        Document document = new Document();

        // 第二步：设置要到出的路径
        // FileOutputStream out = new FileOutputStream(reportPath + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()).toString() + ".pdf");

        //如果是浏览器通过request请求需要在浏览器中输出则使用下面方式
        OutputStream out = response.getOutputStream();

        // 第三步：设置字符 jar包中的字体格式
        // BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);

        //前端无法使用jar包中字体格式，只能按字体文件来设置
        String path = "http://yyn-static-resources-1254950508.file.myqcloud.com/fonts/simsun.ttc";
        BaseFont bfChinese = BaseFont.createFont(path + ",0", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        // 第四步：标题字体样式
        Font fontZH1 = new Font(bfChinese, 12.0F, 1);       // 主标题
        Font fontZH2 = new Font(bfChinese, 8.0F, 1);       // 副标题
        Font fontZH3 = new Font(bfChinese, 8.0F, 1);       // 内容
        // 第五步，将pdf文件输出到磁盘
        PdfWriter writer = PdfWriter.getInstance(document, out);

        // 第六步，打开生成的pdf文件
        document.open();
        List<StatementCost> costList = costMapper.getStatementCost(date, costType);

        DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime createTime = LocalDateTime.now();
        if (CollectionUtils.isNotEmpty(costList)) {
            createTime = costList.get(0).getCreatedDt();
        }

        // 第七步,设置内容
        String title1 = "                      云南腾云信息产业有限公司无合同报表";
        String title2 = "报表统计月份:" + date + "                                                                              报表生成日期:" + sdf.format(createTime);

        document.add(new Paragraph(new Chunk(title1, fontZH1).setLocalDestination(title1)));
        document.add(new Paragraph("\n"));
        document.add(new Paragraph(new Chunk(title2, fontZH2).setLocalDestination(title2)));
        document.add(new Paragraph("\n"));
        // 创建table,注意这里的16是两列的意思,下面通过table.addCell添加的时候必须添加整行内容的所有列
        PdfPTable table1 = new PdfPTable(12);

        table1.setWidthPercentage(100.0F);
        table1.getDefaultCell().setHorizontalAlignment(1);

        PdfPCell cell0 = new PdfPCell();
        cell0.setUseAscender(true);
        cell0.setUseDescender(true);
        cell0.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell0.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell0.setColspan(2);//合并单元格
        cell0.setRowspan(2);
        cell0.setPhrase(new Phrase("项目", fontZH2));

        PdfPCell cell1 = new PdfPCell();
        cell1.setUseAscender(true);
        cell1.setUseDescender(true);
        cell1.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell1.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell1.setColspan(2);//合并单元格
        cell1.setPhrase(new Phrase("门票", fontZH2));

        PdfPCell cell2 = new PdfPCell();
        cell2.setUseAscender(true);
        cell2.setUseDescender(true);
        cell2.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell2.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell2.setColspan(2);//合并单元格
        cell2.setPhrase(new Phrase("线路", fontZH2));
        PdfPCell cell3 = new PdfPCell();
        cell3.setUseAscender(true);
        cell3.setUseDescender(true);
        cell3.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell3.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell3.setColspan(2);//合并单元格
        cell3.setPhrase(new Phrase("机票", fontZH2));
        PdfPCell cell4 = new PdfPCell();
        cell4.setUseAscender(true);
        cell4.setUseDescender(true);
        cell4.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell4.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell4.setColspan(2);//合并单元格
        cell4.setPhrase(new Phrase("酒店", fontZH2));
        PdfPCell cell5 = new PdfPCell();
        cell5.setUseAscender(true);
        cell5.setUseDescender(true);
        cell5.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell5.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell5.setColspan(2);//合并单元格
        cell5.setPhrase(new Phrase("租车", fontZH2));

        table1.addCell(cell0);
        table1.addCell(cell1);
        table1.addCell(cell2);
        table1.addCell(cell3);
        table1.addCell(cell4);
        table1.addCell(cell5);

        table1.addCell(new Paragraph("自营&平台", fontZH3));
        table1.addCell(new Paragraph("清分", fontZH3));
        table1.addCell(new Paragraph("自营&平台", fontZH3));
        table1.addCell(new Paragraph("清分", fontZH3));
        table1.addCell(new Paragraph("自营&平台", fontZH3));
        table1.addCell(new Paragraph("清分", fontZH3));
        table1.addCell(new Paragraph("自营&平台", fontZH3));
        table1.addCell(new Paragraph("清分", fontZH3));
        table1.addCell(new Paragraph("自营&平台", fontZH3));
        table1.addCell(new Paragraph("清分", fontZH3));

        if (CollectionUtils.isNotEmpty(costList)) {
            List<StatementCost> orderList = costList.stream().filter(x -> StatementProjectTypeEnum.ORDER_DIFF.getCode().equals(x.getProjectType())).collect(Collectors.toList());
            List<StatementCost> clearList = costList.stream().filter(x -> StatementProjectTypeEnum.CLEAR_DIFF.getCode().equals(x.getProjectType())).collect(Collectors.toList());

            int orderSize = 0;
            if (CollectionUtils.isNotEmpty(orderList)) {
                orderSize = orderList.size();
            }
            int clearSize = 0;
            if (CollectionUtils.isNotEmpty(clearList)) {
                clearSize = clearList.size();
            }

            int i = 0;
            for (StatementCost a : costList) {
                i++;

                if (i <= 3 || (i > 3 + orderSize && i < 6 + orderSize + 1)) {
                    PdfPCell cell6 = new PdfPCell();
                    cell6.setUseAscender(true);
                    cell6.setUseDescender(true);
                    cell6.setHorizontalAlignment(Element.ALIGN_CENTER);
                    cell6.setVerticalAlignment(Element.ALIGN_MIDDLE);
                    cell6.setColspan(2);//合并单元格
                    cell6.setPhrase(new Phrase(a.getProjectName(), fontZH2));
                    table1.addCell(cell6);
                }

                if (i == 3 + 1 && CollectionUtils.isNotEmpty(orderList)) {
                    PdfPCell cell7 = new PdfPCell();
                    cell7.setUseAscender(true);
                    cell7.setUseDescender(true);
                    cell7.setHorizontalAlignment(Element.ALIGN_CENTER);
                    cell7.setVerticalAlignment(Element.ALIGN_MIDDLE);
                    cell7.setColspan(1);//合并单元格
                    cell7.setRowspan(orderList.size());
                    cell7.setPhrase(new Phrase("差异类型(￥)", fontZH3));
                    table1.addCell(cell7);
//                    table1.addCell(new Paragraph(a.getProjectName(), fontZH3));
                }
                if (CollectionUtils.isNotEmpty(orderList) && 3 + 1 <= i && i < 3 + orderSize + 1) {
                    table1.addCell(new Paragraph(a.getProjectName(), fontZH3));
                }

                if (i == 6 + orderSize + 1 && CollectionUtils.isNotEmpty(clearList)) {
                    PdfPCell cell9 = new PdfPCell();
                    cell9.setUseAscender(true);
                    cell9.setUseDescender(true);
                    cell9.setHorizontalAlignment(Element.ALIGN_CENTER);
                    cell9.setVerticalAlignment(Element.ALIGN_MIDDLE);
                    cell9.setColspan(1);//合并单元格
                    cell9.setRowspan(clearSize);
                    cell9.setPhrase(new Phrase("清分差异类型(￥)", fontZH3));
                    table1.addCell(cell9);
//                    table1.addCell(new Paragraph(a.getProjectName(), fontZH3));
                }

                if (CollectionUtils.isNotEmpty(clearList) && 6 + orderSize + 1 <= i && i < 6 + clearSize + orderSize + 1) {
                    table1.addCell(new Paragraph(a.getProjectName(), fontZH3));
                }
//                table1.addCell(new Paragraph(a.getProjectName(), fontZH3));
                table1.addCell(new Paragraph(a.getTicketSelf().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getTicketClearing().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getLineSelf().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getLineClearing().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getFlightSelf().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getFlightClearing().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getHotelSelf().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getHotelClearing().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getChartererSelf().toString(), fontZH3));
                table1.addCell(new Paragraph(a.getChartererClearing().toString(), fontZH3));
            }
        }
        document.add(table1);
        String title6 = "备注";
        String title7 = "1、应收金额=当月合同生效订单交易净额";
        String title8 = "2、核销金额=当月合同生效核销订单金额";
        String title9 = "3、实收金额=当月合同生效订单交易净额";
        String title10 = "4、交易差异=应收-实收";
        String title11 = "5、平台服务费=若合作模式是平台和清分，则该项=销售价-结算价；若合作模式为自营，则为0";
        String title12 = "6、银行资金=核销金额数据对应的银行资金(即608资金)";
        String title13 = "7、资金差异=核销金额-银行资金";
        String title14 = "8、酒店项目的合作模式中，平台的商户是艺龙";

        document.add(new Paragraph(new Chunk(title6, fontZH2).setLocalDestination(title6)));
        document.add(new Paragraph(new Chunk(title7, fontZH2).setLocalDestination(title7)));
        document.add(new Paragraph(new Chunk(title8, fontZH2).setLocalDestination(title8)));
        document.add(new Paragraph(new Chunk(title9, fontZH2).setLocalDestination(title9)));
        document.add(new Paragraph(new Chunk(title10, fontZH2).setLocalDestination(title10)));
        document.add(new Paragraph(new Chunk(title11, fontZH2).setLocalDestination(title11)));
        document.add(new Paragraph(new Chunk(title12, fontZH2).setLocalDestination(title12)));
        document.add(new Paragraph(new Chunk(title13, fontZH2).setLocalDestination(title13)));
        document.add(new Paragraph(new Chunk(title14, fontZH2).setLocalDestination(title14)));
        // 第八步，关闭document
        document.close();
    }

    @Override
    public void statementCostPdf(String date, String costType, HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (StatementCostTypeEnum.COST.getCode().equals(costType)) {
            statementCostPdf(date, costType, response);
        }
        if (StatementCostTypeEnum.COST_DIFF.getCode().equals(costType)) {
            statementCostDiffPdf(date, costType, response);
        }
        if (StatementCostTypeEnum.NO_CONTRACT.getCode().equals(costType)) {
            statementNoContractPdf(date, costType, response);
        }
        if (StatementCostTypeEnum.REP_CONTRACT.getCode().equals(costType)) {
            statementRepContractPdf(date, costType, response);
        }
    }

}
